Lambda表达式未返回预期的MemberInfo

Bri*_*all 22 c# lambda

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

更新:跳转到最后一个代码块,以获得更有说服力的代码示例.

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

public class C : A { }
Run Code Online (Sandbox Code Playgroud)

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

var a = typeof(C).GetMember("B")[0];
var b = typeof(A).GetMember("B")[0];

Expression<Func<C, string>> c = x => x.B;

var d = (c.Body as MemberExpression).Member;
Run Code Online (Sandbox Code Playgroud)

以下是一些比较的结果:

a == b //false
a == d //false
b == d //true
Run Code Online (Sandbox Code Playgroud)

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

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

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

重复的代码示例由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<Base, string>> parentExp = x => x.Name;
var parentExpMember = (parentExp.Body as MemberExpression).Member;

Expression<Func<Derived, string>> childExp = x => x.Name;
var childExpMember = (childExp.Body as MemberExpression).Member;

parentMember == childMember  //false, good
parentMember == parentExpMember  //true, good
childMember == childExpMember   //false, why?
Run Code Online (Sandbox Code Playgroud)

age*_*t-j 19

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

Expression<Func<C, string>> c = x => x.B; 
Type paramType = c.Parameters[0].Type;  // first parameter of expression
var d = paramType.GetMember((c.Body as MemberExpression).Member.Name)[0];
Run Code Online (Sandbox Code Playgroud)

  • 我看了几个具有类似功能的其他开源项目,这就是他们似乎解决这个问题的方式.谢谢. (2认同)

Eri*_*ert 10

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

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

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

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

  • 我猜_invoked_你指的是通过访问该属性的实际类型.在重述的示例中,childExpMember对于`DeclaredType`具有与`ReflectedType`相同的类型.MSDN声明`ReflectedType`"获取用于获取MemberInfo的此实例的类对象." 由于属性是通过`Derived`类型访问的,因此`ReflectedType`应该指向那个,因为这就是访问成员的方式.我意识到没有"衍生"的实际实例,它只是一个表达式,但它对我来说似乎很奇怪. (3认同)

Che*_*hen 7

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

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<Base, string>> parentExp = x => x.Name;
var parentExpMember = (parentExp.Body as MemberExpression).Member;

Expression<Func<Derived, string>> childExp = x => x.Name;
var childExpMember = (childExp.Body as MemberExpression).Member;

parentMember == childMember  //false, good
parentMember == parentExpMember  //true, good
childMember == childExpMember   //false, why?
Run Code Online (Sandbox Code Playgroud)

在调试时,你会发现childExpMember.ReflectedTypeBase,虽然childMember.ReflectedTypeDerived.AFAIK DeclaringType显示声明成员的位置,同时ReflectedType显示成员被反映到的位置(因为继承/覆盖/等).所以我认为这是一个错误(没有官方确认).