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()());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With