将语句添加到表达式<func <t,bool =“”>&gt;

时间:2015-05-26 09:03:57

标签: c# lambda

我有这个功能:

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.

3 个答案:

答案 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);