C# 在C语言中使用动态Or表达式#

C# 在C语言中使用动态Or表达式#,c#,linq,expression,C#,Linq,Expression,我在程序中使用动态过滤器,如以下解决方案: public static IQueryable<T> MyFilter<T>(this IQueryable<T> queryable) where T : class ,IModel { var someIds = new int[]{1,2,3,4,5}; var userId = 2; Expression<Func<T, bool>>

我在程序中使用动态过滤器,如以下解决方案:

public static IQueryable<T> MyFilter<T>(this IQueryable<T> queryable) where T : class ,IModel
{
        var someIds = new int[]{1,2,3,4,5};
        var userId = 2;

        Expression<Func<T, bool>> predicate1 = e => someIds.Contains(e.Id);
        Expression<Func<T, bool>> predicate2 = e => e.UserId==userId;
        Expression<Func<T, bool>> predicate3 = e => e.CreatedDate != null;

        var pred1 = Expression.Lambda<Func<T, bool>>(System.Linq.Expressions.Expression.Or(predicate1, predicate2));
        var pred2 = Expression.Lambda<Func<T, bool>>(System.Linq.Expressions.Expression.Or(pred1, predicate3));


        var result = queryable
            .Where(pred2);

        return result;
    }
// Note that we only need the Body!
Expression pred1 = Expression.OrElse(Expression.OrElse(predicate1.Body, predicate2.Body), predicate3.Body);

// We change all the predicate2.Parameters[0] to predicate1.Parameters[0] and
// predicate3.Parameters[0] to predicate1.Parameters[0]

var replacer = new SimpleExpressionReplacer(
    /* from */ new[] { predicate2.Parameters[0], predicate3.Parameters[0] }, 
    /* to */ new[] { predicate1.Parameters[0], predicate1.Parameters[0] });

pred1 = replacer.Visit(pred1);

// We use for the new predicate the predicate1.Parameters[0]
var pred2 = Expression.Lambda<Func<T, bool>>(pred1, predicate1.Parameters[0]);

var result = queryable.Where(pred2);
但是,我得到了这个错误:

未为类型“System.Func
2[AnyClass,System.Boolean]”和“System.Func
2[AnyClass,System.Boolean]”定义二进制运算符或

在这一行:

var pred1 = Expression.Lambda<Func<T, bool>>(System.Linq.Expressions.Expression.Or(predicate1, predicate2));
var pred1=Expression.Lambda(System.Linq.Expressions.Expression.Or(predicate1,predicate2));
我怎样才能解决这个问题


事先感谢您的帮助

正如我在评论中所写,有两个不同的问题:

  • 必须使用
    Expression.OrElse
    ,因为
    Expression.Or
    |
    运算符


  • 但真正的问题是不能以这种方式连接Lambda表达式(
    predicate1
    2
    3
    )。连接表达式很复杂,因为
    predicate1
    2
    3
    的输入参数不同(就像
    e1
    e2
    e3
    而不是
    e
    ),而
    pred1
    pred2
    的输入参数将是
    e4
    e5
    ,所以你必须用一些表达式替换

解决方案:

public static IQueryable<T> MyFilter<T>(this IQueryable<T> queryable) where T : class ,IModel
{
        var someIds = new int[]{1,2,3,4,5};
        var userId = 2;

        Expression<Func<T, bool>> predicate1 = e => someIds.Contains(e.Id);
        Expression<Func<T, bool>> predicate2 = e => e.UserId==userId;
        Expression<Func<T, bool>> predicate3 = e => e.CreatedDate != null;

        var pred1 = Expression.Lambda<Func<T, bool>>(System.Linq.Expressions.Expression.Or(predicate1, predicate2));
        var pred2 = Expression.Lambda<Func<T, bool>>(System.Linq.Expressions.Expression.Or(pred1, predicate3));


        var result = queryable
            .Where(pred2);

        return result;
    }
// Note that we only need the Body!
Expression pred1 = Expression.OrElse(Expression.OrElse(predicate1.Body, predicate2.Body), predicate3.Body);

// We change all the predicate2.Parameters[0] to predicate1.Parameters[0] and
// predicate3.Parameters[0] to predicate1.Parameters[0]

var replacer = new SimpleExpressionReplacer(
    /* from */ new[] { predicate2.Parameters[0], predicate3.Parameters[0] }, 
    /* to */ new[] { predicate1.Parameters[0], predicate1.Parameters[0] });

pred1 = replacer.Visit(pred1);

// We use for the new predicate the predicate1.Parameters[0]
var pred2 = Expression.Lambda<Func<T, bool>>(pred1, predicate1.Parameters[0]);

var result = queryable.Where(pred2);

您可以创建一个不带表达式的谓词。或者:

public static IQueryable<T> MyFilter<T>(this IQueryable<T> queryable) where T : class ,IModel
    {
        var someIds = new int[] { 1, 2, 3, 4, 5 };
        var userId = 2;

        var result = queryable
            .Where(e => someIds.Contains(e.Id) || e.UserId == userId || e.CreatedDate != null);

        return result;
    }
公共静态IQueryable MyFilter(此IQueryable查询表),其中T:class,IModel
{
var-someIds=newint[]{1,2,3,4,5};
var userId=2;
var结果=可查询
其中(e=>someIds.Contains(e.Id)| | e.UserId==UserId | | e.CreatedDate!=null);
返回结果;
}
Use
PredicateBuilder
从复制类的源代码,或者安装(它依赖于实体框架),以获取
PredicateBuilder
类。将表达式动态链接在一起很简单:

var predicate = PredicateBuilder.False<int>();
predicate = predicate.Or(x => x > 5);
predicate = predicate.Or(x => x % 2 == 0);
predicate = predicate.Or(x => x == 42 );

var queryable = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }.AsQueryable();
var result = queryable.Where(predicate);
var predicate=PredicateBuilder.False();
谓词=谓词。或(x=>x>5);
谓词=谓词。或(x=>x%2==0);
谓词=谓词。或(x=>x==42);
var queryable=new[]{1,2,3,4,5,6,7,8,9,10}.AsQueryable();
var result=queryable.Where(谓词);

someid.Contains(e.Id)
不正确
IModel
不包含
Id
字段。为什么要使用表达式而不仅仅是Func?您离所需的距离太远了。。。您必须使用
Expression.OrElse
,因为
Expression.Or
运算符。但真正的问题是您不能以这种方式联接Lambda表达式(
predicate1
2
3
)。连接表达式很复杂,因为
predicate1
2
3
的输入参数不同(就像是
e1
e2
e3
而不是
e
),而
pred1
pred2
将有一个
e4
e5
@AlexVoskresenskiy,因为他使用的是一个
IQueryable
,它只对
表达式
有效。你甚至不需要中间的
谓词
变量。将表达式放在
Where
调用中会更简短、更简洁。好的,没错。但我们有许多谓词应该添加到我的表达式中。无论如何,你的回答是正确的,解决了我的问题,谢谢;)