我有这个功能:
public List<T> Find(Expression<Func<T, bool>> query)
{
}
Find(x => x.Id == 4);
在方法Find
内,我想链接And
条件。
类似的东西:
query.And(x => x.Secured == false);//Secured is a memeber inside T like Id.
答案 0 :(得分:1)
您的问题是您希望在通用方法中访问T
的成员。此时T
可能是任何内容,因此编译器不允许您访问Secured
,因为T
可能没有Secured
成员。
您可以将T
强制转换为dynamic
,但这只会将编译时错误更改为运行时错误(加上它的可怕性)。
最好的方法是确保T
实现一些具有安全成员的已知接口。
public List<T> Find(Expression<Func<T, bool>> query) where T : ISecured
答案 1 :(得分:0)
表达式必须“打开”并重建,如下所示:
public List<T> Find<T>(Expression<Func<T, bool>> query)
{
ParameterExpression parameter = query.Parameters[0];
Expression body = query.Body;
MemberExpression property = Expression.Property(parameter, "Secured");
body = Expression.AndAlso(body, Expression.Not(property));
Expression<Func<T, bool>> query2 = Expression.Lambda<Func<T, bool>>(body, parameter);
// Now you can use query2
return null;
}
请注意,我认为此x.Secured == false
等同于!x.Secured
。显然Secured
可能是一个重载==
运算符的奇怪类,但我会忽略这种情况。
根据@Ralf的建议,您甚至可以简单地做两个.Where
。像:
public List<T> Find<T>(Expression<Func<T, bool>> query)
{
ParameterExpression parameter = query.Parameters[0];
MemberExpression property = Expression.Property(parameter, "Secured");
Expression<Func<T, bool>> query2 = Expression.Lambda<Func<T, bool>>(Expression.Not(property), parameter);
return context.Set<T>
.Where(query)
.Where(query2)
.ToList();
}
(我正在使用context.Set<T>
作为示例,这与您使用实体框架时的操作非常相似,但通常几乎所有IQuerable<>
/ IEnumerable<>
都是如此将两个.Where()
视为具有.Where()
条件的单个&&
答案 2 :(得分:-3)
像
这样的东西Find(x => x.Id == 4 && x.Secured == false);