来自MemberExpression的ReflectedType

时间:2014-04-16 09:40:18

标签: c# .net linq-expressions

鉴于此代码:

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
{
}

我希望ReflectedType为SomeDerivedClass,因为它是表达式的参数类型。但它是SomeClass,如果我理解正确的话 - 声明类型。

为什么?

3 个答案:

答案 0 :(得分:4)

表达树如何构建的确切细节很大程度上未指定。唯一重要的是表达式树对应于用于构建表达式树的C#语法。在普通的C#表达式中,只有DeclaringType的等价物,它在IL中编码。该成员根本没有通过反思进行访问,因此没有ReflectedType可以考虑。由于没有ReflectedType要考虑,因此两个不同的PropertyInfo对象与原始源代码的对应度相同。

为了一个可能的原因,请考虑这个有点邪恶的派生类:

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

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

这里,基类的Prop getter 被覆盖,但是原始get_Prop属性编译器生成的getter函数只能通过基类使用。因此,Prop唯一正确的属性getter是SomeClass.get_Prop。即使在静态已知为SomeDerivedClass.get_Prop的对象上访问Prop,也不得使用SomeDerivedClass

将此与内部事实相结合,构建表达式树的C#编译器生成的代码通过获取属性getter方法获取相应的PropertyInfo对象,并要求运行时查找相应的{{1}你有答案:只能从PropertyInfo可靠地获取属性getter方法,因此你也可以从SomeClass获得PropertyInfo

答案 1 :(得分:1)

这是因为表达式的评估结果为PropSomeClass而不是SomeDerivedClass。请注意,SomeDerivedClass仅仅是test lambda参数的类型,因此它与其正文的类型无关,即UnaryExpression访问{{1}中的属性}}。

尝试将SomeClass添加到Prop,您将获得预期的结果。

答案 2 :(得分:-1)

ReflectedType属性检索用于获取此MemberInfo实例的Type对象。如果此MemberInfo对象表示从基类继承的成员,则此值可能与DeclaringType属性的值不同。

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