Lambda Expression: cast parameter to base type

11,420

If I understand your question correctly, you want to create a lambda expression like this:

Func<MyAbstractClass<T>, Object> f = i => ((MyConcreteClass)i).SomeProperty;

Except you want to provide which property is SomeProperty as a parameter. Well, if you want to build that expression programmatically, you have to do exactly the same: have expression parameter i (of type MyAbstractClass<T>), cast it to MyConcreteClass and then access property SomeProperty of that.

public Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
{
    var parameter = Expression.Parameter(typeof(MyAbstractClass<T>), "i");

    var cast = Expression.TypeAs(parameter, property.DeclaringType);

    var getterBody = Expression.Property(cast, property);

    var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(
        getterBody, parameter);

    return exp.Compile();
}

Having said that, I have absolutely no idea why would you want to do that, so you better be really sure this is what you want to do and that there isn't any better way of doing what you actually want to do.

Share:
11,420
NicolaBaldi
Author by

NicolaBaldi

Updated on June 26, 2022

Comments

  • NicolaBaldi
    NicolaBaldi over 1 year

    I'd like to "wrap" the getter function for a specific property that is part of a specific type. I have an abstract class, defined like following:

    public abstract class MyAbstractClass<T> where T : MyType
    {
        // ...
    }
    

    Well, suppose I've a concrete class like the following one:

    public abstract class MyConcreteClass : MyAbstractClass<MyConcreteType>
    {
        // ...
    }
    

    And now, the helper method that should return a wrapper for the getter method:

    private Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property)
    {
        var instanceType = Expression.Parameter(property.DeclaringType, "i");
    
        // Taking getter's "body".
        var getterBody = Expression.Property(instanceType, property);
    
        // Cast to a generic Object.
        var body = Expression.TypeAs(getterBody, typeof(Object));
    
        // Build the expression.
        var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(body, instanceType);
        return exp.Compile();
    }
    

    Just like expected, I get the following exception:

    ParameterExpression of type 'MyConcreteClass' cannot be used for delegate parameter of type 'MyAbstractClass<MyConcreteType>'.

    Is there a way to "force" this kind of casting? Thanks in advance.

  • digaomatias
    digaomatias almost 10 years
    +1 I was looking for a sample of Expression.TypeAs. Thanks for sharing.