向表达式添加 And 语句<Func<T, bool>>

问题描述 投票:0回答:4

我有这个功能:

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.
c# lambda
4个回答
1
投票

您的问题是您想在通用方法中访问

T
的成员。此时
T
可以是任何内容,因此编译器不会让您访问
Secured
,因为
T
可能没有
Secured
成员。

您可以将

T
转换为
dynamic
,但这只会将编译时错误更改为运行时错误(而且这很可怕)。

最好的方法是确保

T
实现一些具有 Secured 成员的已知接口。

public  List<T> Find(Expression<Func<T, bool>> query) where T : ISecured

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()
具有
&&
条件)


0
投票

我有和你类似的需求,最终创建了这个扩展:

public static class LinqExpressionExtensions
{
    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
    {
        if (first == null ) return second;
        if (second == null ) return first;

        var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.And(first.Body, invokedExpr), first.Parameters);
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
    {
        if (first == null ) return second;
        if (second == null ) return first;
        
        var invokedExpr = Expression.Invoke(second, first.Parameters.Cast<Expression>());
        return Expression.Lambda<Func<T, bool>>(Expression.Or(first.Body, invokedExpr), first.Parameters);
    }
}

示例:

System.Linq.Expressions.Expression<Func<MyEntity, bool>> result = null;
System.Linq.Expressions.Expression<Func<MyEntity, bool>> CategoryExpression = null;
if (condition)
{
  CategoryExpression = w => w.Id== 1;
}
else
{
  CategoryExpression = w => w.Id== 2;
}
if (condition2)
{
  Expression<Func<MyEntity, bool>> jointExpression = null;
  jointExpression = w => w.JointId== 3;
  result = CategoryExpression.Or(jointExpression);
}
else
{
   result = CategoryExpression;
}

-4
投票

类似

Find(x => x.Id == 4 && x.Secured == false);
© www.soinside.com 2019 - 2024. All rights reserved.