How can i access the value of a local variable from within an expression tree

By examining an expression tree i can get the value of a constant, instance field and property but not a local variable defined in a method.

Executing the following will output 1, 2, 3 (from the constant, instance field and property) then an exception as i don't know how to get the instance on which the FieldInfo is declared in order to call GetValue() for the local variable.

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));
                }
            }
        }
    }
}

The local variable which has been captured by the lambda and included in the expression tree, will at that time really be a field on some compiler-generated class. This works on my version of .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));
    }
  }
}

Of course, you can also "cheat":

void Test<T>(Expression<Func<T>> func)
{
  Console.WriteLine(func.Compile()());
}

No, you cannot.

Reflection does not extend to reading the values of method variable.

It only handles the declaration metadata of variables. And even then, the compiler may have removed the variable you thought you declared. You allready can access to properties, fields.


不,你不能,因为这些变量在方法范围之外根本不可用。

链接地址: http://www.djcxy.com/p/92586.html

上一篇: 使用Regex进行VB.NET电子邮件验证

下一篇: 我如何从表达式树中访问局部变量的值