我有一组POCO,所有这些都实现了以下简单的界面:
interface IIdObject
{
int Id { get; set; }
}
这些POCO的一个子集实现了这个额外的接口:
interface IDeletableObject : IIdObject
{
bool IsDeleted { get; set; }
}
我有一个类似于这样的存储库层次结构:
IRepository< T> &lt ;: BasicRepository< T> &lt ;: ValidatingRepository< T> (其中T是IIdObject)
我正在尝试向层次结构中添加 FilteringRepository ,以便在执行任何其他查询之前,所有实施IDeletableObject
的POCO都会应用Where(p => p.IsDeleted == false)
过滤器。我的目标是避免仅为IDeletableObjects重复层次结构。
我的第一次尝试看起来像这样:
public override IQueryable<T> Query()
{
return base.Query().Where(t => ((IDeletableObject)t).IsDeleted == false);
}
这适用于LINQ to Objects,但当我切换到EF后端时,我得到:“LINQ to Entities仅支持转换实体数据模型基元类型。”
我继续尝试一些更高级的参数化解决方案,但他们最终失败了,因为我不能在以下情况下使用T协变因某些原因我不太明白:
interface IQueryFilter<out T> // error
{
Expression<Func<T, bool>> GetFilter();
}
我很乐意详细介绍我的更复杂的解决方案,如果它会有所帮助,但我想我会暂时停在这里,希望有人可能有想法让我尝试。
非常感谢!
答案 0 :(得分:1)
这太大而无法发表评论,所以......
您可以动态创建表达式。我已经创建了辅助方法:
public static class ExpressionHelper
{
public static MemberExpression PropertyExpression(this Expression expr,string propertyName)
{
var properties = propertyName.Split('.');
MemberExpression expression = null;
foreach (var property in properties)
{
if (expression == null)
expression = Expression.Property(expr, property);
else
expression = Expression.Property(expression, property);
}
return expression;
}
public static BinaryExpression EqualExpression<T>(this Expression expr, string propertyName, T value)
{
return Expression.Equal(expr.PropertyExpression(propertyName), Expression.Constant(value, typeof(T)));
}
}
然后你可以使用:
//Checking if T implements IDeletableObject
if (typeof(IDeletableObject).IsAssignableFrom(typeof(T)))
{
//a
var parameter = Expression.Parameter(typeof(T), "a");
//a.IsDeleted == false
var where = parameter.EqualExpression("IsDeleted", false);
//a => a.IsDeleted == false
var condition = Expression.Lambda<Func<T, bool>>(where, parameter);
list = list.Where(condition);
}
修改强>
您也可以使用Dynamic Linq Library。它也使用表达式,但不会强迫您考虑它是如何工作的,只需将简单条件写为字符串。我不知道它如何处理bool值。