添加And语句到Expression>
本文关键字:bool And Func Expression 添加 语句 | 更新日期: 2023-09-27 17:50:48
我有这个函数:
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.
你的问题是你想在泛型方法中访问T
的成员。此时T
可以是任何值,所以编译器不会让您访问Secured
,因为T
可能没有Secured
成员。
您可以将T
强制转换为dynamic
,但这只是将编译时错误更改为运行时错误(而且这很可怕)。
最好的方法是确保T
实现一些已知的接口,这些接口有一个Secured成员。
public List<T> Find(Expression<Func<T, bool>> query) where T : ISecured
表达式必须"打开"并重新构建,如下所示:
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()
与&&
条件)
类似
Find(x => x.Id == 4 && x.Secured == false);