Search code examples
c#lambda

Get the object instance from a LambdaExpression


I want to pass an instance of a class to a method using an Expression<T> and retrieve the instance from within the method:

public class MyOb
{
    public void Receive(Expression<Func<Item>> item)
    {
        // Here I would like to get item as Item
        // Have tried various things such as
        var x = ((MemberExpression)(item.Body)).Member;
        
        int y = x.IntProp  // should be 123.
    }
}

public class Item
{
    public int IntProp { get; set; } = 123;
}

MyOb mo = new();
Item myItem = new();
mo.Receive(() => myItem);

Solution

  • That would not be that easy because the compiler will generate a special class to handle closure which will store the value of the local variable (myItem). Something like this should do the trick:

    public static void Receive(Expression<Func<Item>> item)
    {
        if (item.Body is MemberExpression { Expression: ConstantExpression constE })
        {
            var itemValue = constE.Type.GetFields()
                .Where(fi => fi.FieldType.IsAssignableTo(typeof(Item)))
                .Single() // possibly proper validation message if multiple found
                .GetValue(constE.Value);
            var intProp = ((Item)itemValue).IntProp; // your value
            Console.WriteLine(intProp); // will print 123 for your code
        }
    }