How to get the child declaring type from an expression?
.net, c#, lambda, linq
Solution
No - this is an accurate representation of what gets emitted by the C# compiler. The override is effectively ignored when looking for the member - the compiler only cares about the type that originally declared the member. You can see this for yourself by compiling code and then looking at the IL. This method:
static void Main()
{
Child c = new Child();
string x = c.Value;
}
is compiled into this IL:
IL_0000: nop
IL_0001: newobj instance void Child::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance string Parent::get_Value()
IL_000d: stloc.1
IL_000e: ret
One point of trivia: the VB compiler doesn't work the same way, so this method:
Public Shared Sub Main(Args As String())
Dim x As Child = New Child()
Dim y As String = x.Value
End Sub
is compiled as:
IL_0000: newobj instance void [lib]Child::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: callvirt instance string [lib]Child::get_Value()
IL_000c: stloc.1
IL_000d: ret
Problem
I have a Parent / Child class hierarchy where the Parent abstractly declares a string property and the Child class implements it: ``` abstract class Parent { public abstract string Value { get; } } class Child : Parent { public override string Value { get { return null; } } } ``` When I use an expression that explicitly (or implicitly) uses the Child class, I expect the Expressions's MemberInfo's DeclaringType to be 'Child', but instead it is Parent: ``` Child child = new Child(); Expression<Func<string>> expression = (() => child.Value); MemberInfo memberInfo = expression.GetMemberInfo(); Assert.AreEqual(typeof(Child), memberInfo.DeclaringType); // FAILS! ``` The assertion fails because the DeclaringType is Parent. Is there something I can do in declaring my expression or consuming it to reveal the actual use of the Child type? NOTE: GetMemberInfo() above as an extension method (I even forgot we had written this!): ``` public static class TypeExtensions { /// <summary> /// Gets the member info represented by an expression. /// </summary> /// <param name="expression">The member expression.</param> /// <returns>The member info represeted by the expression.</returns> public static MemberInfo GetMemberInfo(this Expression expression) { var lambda = (LambdaExpression)expression; MemberExpression memberExpression; if (lambda.Body is UnaryExpression) { var unaryExpression = (UnaryExpression)lambda.Body; memberExpression = (MemberExpression)unaryExpression.Operand; } else memberExpression = (MemberExpression)lambda.Body; return memberExpression.Member; } } ```