如何从表达式树中访问局部变量的值

Dan*_*Dan 8 c# reflection

通过检查表达式树,我可以获得常量,实例字段和属性的值,但不能获取方法中定义的局部变量.

执行以下操作将输出1,2,3(来自常量,实例字段和属性)然后是异常,因为我不知道如何获取声明FieldInfo的实例以便为本地调用GetValue()变量.

using System;
using System.Linq.Expressions;
using System.Reflection;

namespace Example
{
    class Program
    {
        private int _intField = 2;

        static void Main()
        {
            new Program().Run();
            Console.ReadLine();
        }

        private void Run()
        {
            IntProp = 3;
            var intVariable = 4;
            Test(() => 1);
            Test(() => _intField);
            Test(() => IntProp);
            Test(() => intVariable);
        }

        public int IntProp { get; set; }

        void Test<T>(Expression<Func<T>> func)
        {
            var body = func.Body;

            if (body.NodeType == ExpressionType.Constant)
            {
                Console.WriteLine(((ConstantExpression)body).Value);
            }
            else
            {
                var memberExpression = body as MemberExpression;

                var @object = memberExpression.Member.DeclaringType == GetType()
                    ? this
                    : null; //Can I do anything here? Instance of the method the variable is defined in?

                if (memberExpression.Member.MemberType == MemberTypes.Field)
                {
                    Console.WriteLine(((FieldInfo)memberExpression.Member).GetValue(@object));
                }
                else if (memberExpression.Member.MemberType == MemberTypes.Property)
                {
                    Console.WriteLine(((PropertyInfo)memberExpression.Member).GetValue(@object));
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jep*_*sen 4

已被 lambda 捕获并包含在表达式树中的局部变量此时将真正成为某个编译器生成的类上的字段。这适用于我的 .NET 版本:

void Test<T>(Expression<Func<T>> func)
{
  var body = func.Body;

  if (body.NodeType == ExpressionType.Constant)
  {
    Console.WriteLine(((ConstantExpression)body).Value);
  }
  else
  {
    var memberExpression = (MemberExpression)body;

    var @object = 
      ((ConstantExpression)(memberExpression.Expression)).Value; //HERE!

    if (memberExpression.Member.MemberType == MemberTypes.Field)
    {
      Console.WriteLine(((FieldInfo)memberExpression.Member).GetValue(@object));
    }
    else if (memberExpression.Member.MemberType == MemberTypes.Property)
    {
      Console.WriteLine(((PropertyInfo)memberExpression.Member).GetValue(@object));
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,你也可以“作弊”:

void Test<T>(Expression<Func<T>> func)
{
  Console.WriteLine(func.Compile()());
}
Run Code Online (Sandbox Code Playgroud)