Polymorphism in Expression trees

While trying to be extra-clever today, I found a potential nasty issue when dealing with strongly-typed reflection.  Suppose I have a simple hierarchy of objects:

public abstract class Base
{
    public abstract string Foo { get; }
}

public class Child : Base
{
    public override string Foo
    {
        get { return "asdf"; }
    }
}

An abstract base class and a child class that implements the one abstract member.  Suppose now we want to do some strongly-typed reflection with the child type:

[Test]
public void PolymorphicWeirdness()
{
    Expression<Func<Child, object>> func = child => child.Foo;

    var body = (MemberExpression) func.Body;
    body.Member.DeclaringType.ShouldEqual(typeof (Child));
}

Many frameworks, AutoMapper being one of them, take advantage of this strongly-typed reflection to get to MemberInfo information on the property or method used in the expression.  Unfortunately, the above test fails.  Instead of the MemberInfo’s DeclaringType being “Child”, it’s “Base”.

If I’m using Expressions to do things like interrogate the MemberInfo for things like custom attributes, I won’t be getting the whole story here.  Lots of other OSS tools use Expressions quite a bit, so I’m very curious to see what those tools do with this behavior.  Note, it’s only the Expression tree with the polymorphism issue.  Once you compile the Expression, all of the normal CLR resolution rules are applied.

This seems like someone would have written about this issue by now, so I’m off to do some sleuthing to see how others deal with this.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in C#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.OdeToCode.com/blogs/scott/ Scott Allen

    Perhaps you should be looking at the parameter type for the expression instead of the declaring type of the property?

    i.e.

    ((MemberExpression)func.Body).Expression.Type

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Scott

    That does let me get to the correct type of the parameter, but I’ll have to re-interrogate that type to get the correct MemberInfo. I ran into this trying to get attributes from a Property, and found it didn’t have the derived type’s MemberInfo.

  • http://www.lostechies.com/members/chadmyers/default.aspx chadmyers

    Does the test work if you use string-based reflection? I’m probably wrong, but your assertion seems incorrect.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Chad

    Yeah, going off of typeof(Child) would work. Nate Kohari made my test pass:

    http://pastie.org/399708

    I see this as a crazy hack, and means I can’t trust any MemberInfo directly in an expression tree.

    It’s also borked for MethodCallExpression as well.

  • http://emiajnet.blogspot.com Jaime

    Would this do the trick?
    body.Expression.Type == typeof(Child)