添加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.

添加And语句到Expression<Func<T, bool>>

你的问题是你想在泛型方法中访问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);