Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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# 将表达式引用解析为实际值_C#_.net_Lambda_Expression - Fatal编程技术网

C# 将表达式引用解析为实际值

C# 将表达式引用解析为实际值,c#,.net,lambda,expression,C#,.net,Lambda,Expression,我希望记录表达式中的实际值,而不是对表达式中使用的属性/字段/常量的引用。我这里有一把小提琴:它的代码(为子孙后代)是: 但我想看看这样的东西 f => ((((f.Hue == Hues.Red) AndAlso (f.Shape == "Sphere")) AndAlso (f.Size == "Small")) AndAlso Not(f.IsDeleted)) 这是可以做到的,还是我遗漏了表达式的要点?所以需要的是去掉闭包。为此,需要重写表达式树(请注意,表达式访问者中并非考虑所

我希望记录表达式中的实际值,而不是对表达式中使用的属性/字段/常量的引用。我这里有一把小提琴:它的代码(为子孙后代)是:

但我想看看这样的东西

f => ((((f.Hue == Hues.Red) AndAlso (f.Shape == "Sphere")) AndAlso (f.Size == "Small")) AndAlso Not(f.IsDeleted))

这是可以做到的,还是我遗漏了表达式的要点?

所以需要的是去掉闭包。为此,需要重写表达式树(请注意,表达式访问者中并非考虑所有情况):


您的表达式正在关闭
输入
。为什么不在中传递第二个
Foo
并在表达式中使用它:
expression
感谢@Sean的提示,但这个精心设计的示例最接近于读取的代码,在这里无法共享。它也不会“扩展”或“解决”对其价值观的引用。我认为这就是问题所在。涵盖所有案件是一项非常重要的任务。即使在这个简单的示例中,我们也遇到了问题:
运行时异常(第1行):通过方法“closuresolver.VisitMember(System.Linq.Expressions.MemberExpression)”尝试访问字段“Program+c_uDisplayClass0_0.input”失败。
感谢您的反馈。我是针对.NET Core 3.1进行测试的-该示例在那里运行:我还能够在本地使用.NET Framework 4.7运行该示例,但在DotNetFiddle中没有-一定存在安全配置问题,无法执行该逻辑。请查找我在GitHub上启动的一个项目:现在该逻辑处理更多的情况,包括方法参数,索引器和静态字段/属性。NuGet软件包也可用。
f => ((((f.Hue == Hues.Red) AndAlso (f.Shape == value(Program+<>c__DisplayClass0_0).input.Shape)) AndAlso (f.Size == value(Program+<>c__DisplayClass0_0).input.SizeType.ToString())) AndAlso Not(f.IsDeleted))
f => ((((f.Hue == Hues.Red) AndAlso (f.Shape == "Sphere")) AndAlso (f.Size == "Small")) AndAlso Not(f.IsDeleted))
public static void Main()
{
    // ...

    var updated = (Expression<Func<Foo, bool>>)
        new ClosureResolver().Visit(expression);

    // Outputs:
    // f => ((((f.Hue == Hues.Red) AndAlso (f.Shape == "Sphere")) AndAlso (f.Size == "Small")) AndAlso Not(f.IsDeleted))
    Console.WriteLine(updated);
}


public class ClosureResolver : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Arguments.Count == 0)
        {
            var objExpr = Visit(node.Object);

            if (objExpr is ConstantExpression objConstExpr)
            {
                var res = node.Method.Invoke(objConstExpr.Value, new object[0]);
                return Expression.Constant(res);
            }
        }

        return base.VisitMethodCall(node);
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        var childExpr = Visit(node.Expression);

        if (childExpr is ConstantExpression constExpr)
        {
            if (node.Member is FieldInfo field)
            {
                var constVal = field.GetValue(constExpr.Value);
                return Expression.Constant(constVal);
            }
            else if (node.Member is PropertyInfo prop)
            {
                var constVal = prop.GetValue(constExpr.Value);
                return Expression.Constant(constVal);
            }
        }

        return base.VisitMember(node);
    }
}
static void ClosureDemo()
{
    var input = new Foo { Shape = "Sphere" };

    Expression<Func<Foo, bool>> expr = f =>
        f.Shape == input.Shape;

    var updated = (Expression<Func<Foo, bool>>) 
        new ClosureResolver().Visit(expr);

    var fn = expr.Compile();
    var updatedFn = updated.Compile();


    Console.WriteLine(fn(input)); // True
    Console.WriteLine(updatedFn(input)); // True

    input.Shape = "Cube";

    Console.WriteLine(fn(input)); // True
    Console.WriteLine(updatedFn(input)); // False
}