【问题标题】:C# Expression Tree compile issueC# 表达式树编译问题
【发布时间】:2020-09-09 19:49:28
【问题描述】:

我有以下表达式树,当我编译表达式树时它给我一个错误。

        string tenantId = "tst user";

        Expression<Func<MongoIdentityUser, bool>> filterToUse = t => t.IsActive == true && t.IsApproved == true;
        var expConst = Expression.Constant(tenantId);
        var paramExp = Expression.Parameter(typeof(MongoIdentityUser), "t");
        var callExp = Expression.PropertyOrField(paramExp, "TenantId");
        var equalExp = Expression.Equal(callExp,Expression.Constant(null));
        var equalExp2 = Expression.Equal(callExp, expConst);
        var conditionExp = Expression.Condition(equalExp, Expression.Constant(true), equalExp2);
        var AndExp = Expression.AndAlso(filterToUse.Body, conditionExp);

        var lambdaExp1 = Expression.Lambda<Func<MongoIdentityUser, bool>>(AndExp, paramExp);
       
        Console.WriteLine(lambdaExp1.Compile());

The generated expression is as follows

t => (((t.IsActive == True) AndAlso (t.IsApproved == True)) AndAlso IIF((t.TenantId == null), True, (t.TenantId == "tst user")))

但是当我调用 lambdaExp1.Compile() 时,它给了我以下错误

【问题讨论】:

  • 你检查this的答案了吗?

标签: c# .net asp.net-core-mvc


【解决方案1】:

如果你更换你的

var paramExp = Expression.Parameter(typeof(MongoIdentityUser), "t");

var paramExp= filterToUse.Parameters[0];

那么它应该可以工作了。

您不能将表达式filterToUse 的参数引用为"t" (是否会尝试捕获名为 t 的局部范围变量?)

【讨论】:

    【解决方案2】:

    filterToUseparamExp 中的 t 参数被 LambdaCompiler 视为不同的参数(ParameterExpression 不会覆盖 EqualsGetHashcode 并用作 Definitions 字典中的键) .

    如果您在项目中添加了 Entity Framework Core,则可以使用 ReplacingExpressionVisitort 替换为 paramExp

    var filter = ReplacingExpressionVisitor.Replace(filterToUse.Parameters.First(), paramExp, filterToUse.Body); 
    var AndExp = Expression.AndAlso(filter, conditionExp);
    ....
    

    如果您无法使用,您可以编写自己的。或者使用filterToUse.Parameters.First()(因为你只有一个表达式可以扩展/组合)作为你的paramExp,即:

    var paramExp = filterToUse.Parameters.First();
    

    【讨论】: