.net 获取在C#表达式值内部传递的值

lstz6jyr  于 2023-01-31  发布在  .NET
关注(0)|答案(1)|浏览(126)

我有下面的班级

public class TestClass
{
    public int TestProperty { get; set; }
}

我有下面的代码

int x = 1;
Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == x;
Console.WriteLine(predicate.ToString());

predicate.ToString()正在返回c => (c.TestProperty == value(Program+<>c__DisplayClass0_0).x)
是否有方法计算表达式以返回c => (c.TestProperty == 1)
请注意,无法创建如下所示设置了x值的表达式

Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == 1;
5f0d552i

5f0d552i1#

这不是很容易和健壮(依赖于当前的表达式生成模式),但可以通过访问者实现:

class MySimpleConstantReplacingVisitor : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression is ConstantExpression ce && node.Member is FieldInfo fe) // possibly check as PropertyInfo JIC
        {
            return Expression.Constant(fe.GetValue(ce.Value));
        }

        return base.VisitMember(node);
    }
}

和用法:

int xx = 1;
Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == xx;
var modifiedExpression = new MySimpleConstantReplacingVisitor().Visit(predicate);
Console.WriteLine(modifiedExpression.ToString()); // prints "c => (c.TestProperty == 1)"

请注意,这仅涵盖简单情况(就像例子中的那个),可能会有很多警告。我不知道是否有库可以做你需要的事情,但是有很多库可以处理表达式树的分析。就像几乎所有基于LINQ的ORM一样--比如EF Core(例如,请参见ParameterExtractingExpressionVisitor,检查闭包部分可能会很有趣)。或者Serialize.Linq库。

相关问题