Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 组合两个linq表达式_C#_Asp.net_Linq_Expression - Fatal编程技术网

C# 组合两个linq表达式

C# 组合两个linq表达式,c#,asp.net,linq,expression,C#,Asp.net,Linq,Expression,我有两个要组合的linq表达式,但我的代码在二进制运算符中给了我一个错误,并且没有为类型'System.Func`2[Web.Entities.Customer,System.Boolean]'和'System.Func`2[Web.Entities.Customer,System.Boolean]'定义 我有两个表达式,例如 Expression<Func<Customer, bool>> filter = c => c.Active; Expression&

我有两个要组合的linq表达式,但我的代码在二进制运算符中给了我一个错误,并且没有为类型
'System.Func`2[Web.Entities.Customer,System.Boolean]'
'System.Func`2[Web.Entities.Customer,System.Boolean]'定义

我有两个表达式,例如

 Expression<Func<Customer, bool>> filter = c => c.Active;
 Expression<Func<Customer, bool>> filterz = c => c.Visible;
expressionfilter=c=>c.Active;
表达式filterz=c=>c.可见;
然后我把它们结合起来

 filter = Expression.Lambda<Func<Customer, bool>>(Expression.And(filter, filterz));
filter=Expression.Lambda(Expression.And(filter,filterz));
关于这个问题有什么帮助吗

谢谢

下面是答案中给出的Updated代码

public class SwapVisitor : ExpressionVisitor
{

    private readonly Expression from, to;
    public SwapVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

filter = Expression.Lambda<Func<Customer, bool>>(Expression.AndAlso(
                        new SwapVisitor(filter.Parameters[0], filterz.Parameters[0]).Visit(filter.Body), filterz.Body), filterz.Parameters)
公共类SwapVisitor:ExpressionVisitor
{
私有只读表达式from、to;
公共SwapVisitor(表达式from,表达式to)
{
this.from=from;
这个;
}
公共重写表达式访问(表达式节点)
{
返回节点==从?到:基本访问(节点);
}
}
filter=Expression.Lambda(Expression.AndAlso(
新建SwapVisitor(filter.Parameters[0],filterz.Parameters[0])。访问(filter.Body),filterz.Body,filterz.Parameters)

如果您在每个过滤器中使用相同的
客户
,您可以尝试:

        Expression<Func<Customer, bool>> filter = c => c.Active;
        Expression<Func<Customer, bool>> filter2 = c => c.Visible;

        var body = Expression.AndAlso(filter.Body, Expression.Invoke(filter2, filter.Parameters[0]));

        filter = Expression.Lambda<Func<Customer, bool>>(body, filter.Parameters);
        var applyFilter = filter.Compile();

        var customer = new Customer() { Visible = true, Active = true};
        Console.WriteLine(applyFilter(customer));

        customer.Active = false;
        Console.WriteLine(applyFilter(customer));

        customer.Visible = false;
        Console.WriteLine(applyFilter(customer));
expressionfilter=c=>c.Active;
表达式filter2=c=>c.可见;
var body=Expression.AndAlso(filter.body,Expression.Invoke(filter2,filter.Parameters[0]);
filter=Expression.Lambda(body,filter.Parameters);
var applyFilter=filter.Compile();
var customer=new customer(){Visible=true,Active=true};
Console.WriteLine(applyFilter(客户));
customer.Active=false;
Console.WriteLine(applyFilter(客户));
customer.Visible=false;
Console.WriteLine(applyFilter(客户));
表达式过滤器1=c=>c.激活;
表达式filter2=c=>c.可见;
var参数=表达式参数(类型(客户),“x”);
var filter=Expression.Lambda(
安达尔索(
Expression.Invoke(filter1,参数),
Expression.Invoke(filter2,参数)
),参数
);

您已经可以在存储库中使用表达式,而无需外部组合它们:

var yourContext = getContext();
var filtered = yourContext.Where(filter).Where(filter2);
在这种情况下,组合是不必要的,这种方法也可以在不影响效率的情况下工作

如果需要合并:

请尝试使用以下访客助手:

public class ReplacementVisitor : System.Linq.Expressions.ExpressionVisitor
{
    private readonly Expression _oldExpr;
    private readonly Expression _newExpr;
    public ReplacementVisitor(Expression oldExpr, Expression newExpr)
    {
        _oldExpr = oldExpr;
        _newExpr = newExpr;
    }

    public override Expression Visit(Expression node)
    {
        if (node == _oldExpr)
            return _newExpr;
        return base.Visit(node);
    }
}
我们需要它,因为过滤表达式使用不同的参数实例。为了组合,我们需要它们使用相同的参数实例。本课程帮助我们完成以下工作:

Expression<Func<Customer, bool>> filter = c => c.Active;
Expression<Func<Customer, bool>> filterz = c => c.Visible;

var newParameter = Expression.Parameter(typeof(Customer), "x");
var visitor1 = new ReplacementVisitor(filter.Parameters[0], newParameter);
var visitor2 = new ReplacementVisitor(filterz.Parameters[0], newParameter);

var newLambda = Expression.Lambda(
    Expression.AndAlso(
        visitor1.Visit(filter.Body),
        visitor2.Visit(filterz.Body)
    ),
    newParameter
);
expressionfilter=c=>c.Active;
表达式filterz=c=>c.可见;
var newParameter=表达式.参数(typeof(Customer),“x”);
var visitor1=new ReplacementVisitor(filter.Parameters[0],newParameter);
var visitor2=new ReplacementVisitor(filterz.Parameters[0],newParameter);
var newLambda=表达式.Lambda(
安达尔索(
访问者1.访问者(过滤器主体),
探访者2.探访(过滤体)
),
新参数
);

您希望在结果中得到什么?我希望将组合表达式传递到我的通用存储库,并传回所有活动和可见的客户。我已经有了一个可以工作的通用存储库,我发送了一个表达式过滤器,并通过过滤器传回数据库表值。这不起作用,因为表达式体使用不同的参数实例。你确定他需要按位AND运算吗?我需要组合,因为在枚举中设置的条件上的解除挂起将操作不同的筛选条件。上面的代码是精简的基本版本。这也不起作用。它通过helper方法,但没有返回任何内容。哪个方法<在我的示例中,code>newLambda
是您需要的组合表达式。
Expression<Func<Customer, bool>> filter = c => c.Active;
Expression<Func<Customer, bool>> filterz = c => c.Visible;

var newParameter = Expression.Parameter(typeof(Customer), "x");
var visitor1 = new ReplacementVisitor(filter.Parameters[0], newParameter);
var visitor2 = new ReplacementVisitor(filterz.Parameters[0], newParameter);

var newLambda = Expression.Lambda(
    Expression.AndAlso(
        visitor1.Visit(filter.Body),
        visitor2.Visit(filterz.Body)
    ),
    newParameter
);