简体   繁体   English

C#表达式树编译问题

[英]C# Expression Tree compile issue

I have the following Expression tree which gives me an error when I compile the expression tree.我有以下表达式树,它在编译表达式树时出现错误。

        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")))

But when I called lambdaExp1.Compile() it gives me the following error但是当我调用 lambdaExp1.Compile() 时,它给了我以下错误在此处输入图片说明

If you replace your如果你更换你的

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

with

var paramExp= filterToUse.Parameters[0];

Then it should work.那么它应该工作。

You can't reference the parameter of the Expression filterToUse as "t" (Would that instead try to capture a local scope variable called t ?)您不能将 Expression filterToUse的参数引用为"t" (是否会尝试捕获名为t的局部范围变量?)

The t parameter in filterToUse and paramExp are treated as different ones by LambdaCompiler ( ParameterExpression does not override Equals and GetHashcode and is used as key in Definitions dictionary). filterToUseparamExp中的t参数被LambdaCompiler视为不同的ParameterExpressionParameterExpression不会覆盖EqualsGetHashcode并用作Definitions字典中的键)。

If you have Entity Framework Core added to your project you can use ReplacingExpressionVisitor to replace t with paramExp :如果您将 Entity Framework Core 添加到您的项目中,您可以使用ReplacingExpressionVisitort ReplacingExpressionVisitorparamExp

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

If it is not available for you, you can write your own one.如果它不适合你,你可以自己写一个。 Or use filterToUse.Parameters.First() (since you have only one expression to extend/combine) as your paramExp , ie:或者使用filterToUse.Parameters.First() (因为你只有一个表达式来扩展/组合)作为你的paramExp ,即:

var paramExp = filterToUse.Parameters.First();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM