Lambda表达式未返回预期的MemberInfo

我遇到了一个我没想到的问题。 一个例子可能比一段更好地说明我的问题:

更新:跳过最后一个代码块,以获得更具说服力的代码示例。

public class A { public string B { get; set; } } public class C : A { } 

以下是方法中的一些代码:

 var a = typeof(C).GetMember("B")[0]; var b = typeof(A).GetMember("B")[0]; Expression<Func> c = x => xB; var d = (c.Body as MemberExpression).Member; 

以下是一些比较的结果:

 a == b //false a == d //false b == d //true 

前两个有些出乎意料。 我知道即使B不是虚拟的,C也可以用new运算符定义一个具有相同名称的属性,但在这种情况下我没有。

第二个对我来说真是最令人惊讶的(这是我问题的核心)。 即使lambda的参数明确定义为C类型,它仍然返回它,就好像从基类访问属性一样。

我正在寻找的是一种从lambda表达式获取MemberInfo的方法,就好像我已经使用参数类型的reflection来获取MemberInfo。 我的项目本质上将MemberInfos存储在各种字典中,它需要具有可以通过提供lambda表达式来访问元素的function。

由Danny Chen重述的代码示例

 public class Base { public string Name { get; set; } } public class Derived : Base { } //in Main var parentMember = typeof(Base).GetMember("Name")[0]; var childMember = typeof(Derived).GetMember("Name")[0]; Expression<Func> parentExp = x => x.Name; var parentExpMember = (parentExp.Body as MemberExpression).Member; Expression<Func> childExp = x => x.Name; var childExpMember = (childExp.Body as MemberExpression).Member; parentMember == childMember //false, good parentMember == parentExpMember //true, good childMember == childExpMember //false, why? 

取表达式(第一个)参数的类型,然后说

 Expression> c = x => xB; Type paramType = c.Parameters[0].Type; // first parameter of expression var d = paramType.GetMember((c.Body as MemberExpression).Member.Name)[0]; 

我正在寻找的是一种从lambda表达式获取MemberInfo的方法,就好像我已经使用参数类型的reflection来获取MemberInfo。

这不是lambdas上的表达式树转换旨在提供的服务。 如果您要使用“off label”function,那么您可能无法获得所需的结果。

表达式树的目的是以适合在运行时分析的forms提供编译器对表达式的语义分析,而不是为了构造可以远程访问数据库的查询对象而编译时间。

编译器的正确语义分析是Name被声明为Base的属性并在Derived的实例上调用 ,因此这正是从结果表达式树中获取的信息。

好问题。 我使用其他一些名字来使它更清晰。

 public class Base { public string Name { get; set; } } public class Derived : Base { } //in Main var parentMember = typeof(Base).GetMember("Name")[0]; var childMember = typeof(Derived).GetMember("Name")[0]; Expression> parentExp = x => x.Name; var parentExpMember = (parentExp.Body as MemberExpression).Member; Expression> childExp = x => x.Name; var childExpMember = (childExp.Body as MemberExpression).Member; parentMember == childMember //false, good parentMember == parentExpMember //true, good childMember == childExpMember //false, why? 

调试时,您会发现childExpMember.ReflectedTypeBase ,而childMember.ReflectedTypeDerived 。 AFAIK DeclaringType显示DeclaringType成员的位置,而ReflectedType显示成员被reflection到的位置(因为inheritance/覆盖/等)。 所以我认为这是一个错误 (没有官方确认)。

我相信你需要将标志“FlattenHierarchy”传递给GetMember的bindingAttr参数。

来自MSDN:

指定应返回层次结构中的公共和受保护静态成员。 不返回inheritance类中的私有静态成员。 静态成员包括字段,方法,事件和属性。 不返回嵌套类型。