由于每种IPersisted
类型都会有自己的表达式,因此我会将其作为IPersisted
. 所以现在你有了某种多态性。
就像是?
interface IPersisted<T> where T: IPersisted<T>
{
Expression<Func<T, bool>> Predicate { get; }
}
class Repo<T> where T : IPersisted<T>, new()
{
public IQueryable<T> Get()
{
var dummy = new T();
return _queryable.Where(dummy.Predicate);
}
}
class Deletable : IPersisted<Deletable>
{
public Deletable()
{
}
public Expression<Func<Deletable, bool>> Predicate
{
get { return x => !x.IsDeleted; }
}
bool IsDeleted { get; set; }
}
我认为您在这里需要的是某种静态多态性,但由于 C# 不提供,您可能需要为自己创建一个虚拟实例,只是为了获得表达式。
如果你不能有一个默认的构造函数,那么你可以依赖FormatterServices.GetUninitializedObject(t)
. 您可以Get
像这样调整您的方法:
public IQueryable<T> Get()
{
var dummy = (T)FormatterServices.GetUninitializedObject(typeof(T));
return _queryable.Where(dummy.Predicate);
}
可能有很多事情需要注意的两件事FormatterServices.GetUninitializedObject
:
它不会初始化任何东西或运行构造函数,但这对我们来说应该不是问题。
它相对较慢。应该没什么大不了的,因为您可以缓存实例 :) 类似:
class Repo<T> where T : IPersisted<T>
{
//caching mechanism: this is run only once per instance; you can make it
//static if this shud be run only once the entire lifetime of application
readonly T dummy = (T)FormatterServices.GetUninitializedObject(typeof(T));
public IQueryable<T> Get()
{
return _queryable.Where(dummy.Predicate);
}
}
如果确切的表达式不重要,那么您可以摆脱对象实例化。就像是:
interface IPersisted<T> where T: IPersisted<T>
{
Func<T, bool> Predicate { get; }
}
class Repo<T> where T : IPersisted<T>
{
public IQueryable<T> Get()
{
return _queryable.Where(x => x.Predicate(x));
}
}
class Deletable : IPersisted<Deletable>
{
public Func<Deletable, bool> Predicate
{
get { return x => !x.IsDeleted; }
}
}
如果保留的原始定义IPersisted
很重要,那么您可以将其设为非泛型。不确定这是否会使它的强类型降低。
interface IPersisted
{
Expression<Func<object, bool>> Predicate { get; }
}
class Repo<T> where T : IPersisted
{
public IQueryable<T> Get()
{
return _queryable.Where(dummy.Predicate);
}
}
class Deletable : IPersisted
{
public Expression<Func<object, bool>> Predicate
{
get { return x => !((Deletable)x).IsDeleted; }
}
}
上面的方法可以通过寻找一个方法来进行更强的类型化,IPersisted
但不需要足够好的约束:
interface IPersisted
{
Expression<Func<T, bool>> GetPredicate<T>() where T : IPersisted;
}
class Repo<T> where T : IPersisted
{
public IQueryable<T> Get()
{
return _queryable.Where(dummy.GetPredicate<T>());
}
}
class Deletable : IPersisted
{
Expression<Func<T, bool>> IPersisted.GetPredicate<T>() //made it explicit
{
return x => ((Deletable)(object)x).IsDeleted;
}
}
注意:Predicate
如果在类之外没有意义,请明确实现Repo<T>
。