Question

Given this code:

static void Main(string[] args)
{
    Expression<Func<SomeDerivedClass, object>> test = i => i.Prop;
    var body = (UnaryExpression) test.Body;
    Console.WriteLine(((MemberExpression) body.Operand).Member.ReflectedType);
}

public class SomeClass
{
    public int Prop { get; private set; }
}

public class SomeDerivedClass : SomeClass
{
}

I would have expected ReflectedType to be SomeDerivedClass given that it is the type of the parameter for the expression. But it is SomeClass, which is - if i understand correctly - the declaring type.

Why is that?

Was it helpful?

Solution

The precise details of how expression trees get built are largely unspecified. The only thing that matters is that the expression tree corresponds to the C# syntax used to build the expression tree. In an ordinary C# expression, there is only the equivalent of DeclaringType, which gets encoded in the IL. The member isn't accessed through reflection at all, so there is no ReflectedType to consider. Because there is no ReflectedType to consider, the two different PropertyInfo objects corresponds equally well to the original source code.

For a potential reason why, consider this somewhat evil derived class:

public class SomeClass
{
    public int Prop { get; set; }
}

public class SomeDerivedClass : SomeClass
{
    public int get_Prop() { return 4; }
}

Here, the base class's Prop getter is not overridden, but the original get_Prop property compiler-generated getter function is only available through the base class. Therefore, the only correct property getter for Prop is SomeClass.get_Prop. SomeDerivedClass.get_Prop must not be used, even if Prop is accessed on an object statically known to be a SomeDerivedClass.

Combine this with the fact that internally, the C# compiler-generated code to build the expression tree obtains the appropriate PropertyInfo objects by getting the property getter methods, and asking the runtime to find the corresponding PropertyInfo, and you have your answer: the property getter method can only reliably be obtained from SomeClass, therefore you will also get the PropertyInfo from SomeClass.

OTHER TIPS

That's because the expression evaluates to Prop which is defined in SomeClass and not in SomeDerivedClass. Notice that SomeDerivedClass is merely the type of your test lambda parameter, so it has nothing to do with the type of its body, which is an UnaryExpression accessing a property located in SomeClass.

Try also adding Prop to SomeDerivedClass, and you'll get your expected result.

The ReflectedType property retrieves the Type object that was used to obtain this instance of MemberInfo. This may differ from the value of the DeclaringType property if this MemberInfo object represents a member that is inherited from a base class.

http://msdn.microsoft.com/en-us/library/system.reflection.memberinfo.reflectedtype.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top