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?
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
.