【发布时间】:2011-12-29 17:32:08
【问题描述】:
我在 .NET/Reflection 中遇到了一个奇怪的行为,找不到任何解决方案/解释:
class A
{
public virtual string TestString { get; set; }
}
class B : A
{
public override string TestString
{
get { return "x"; }
}
}
因为属性只是成对的函数(get_PropName()、set_PropName()),只覆盖“get”部分应该保留“set”部分,因为它在基类中。如果您尝试实例化 B 类并将值分配给 TestString,就会发生这种情况,它使用 A 类的实现。
但是如果我在反射中查看 B 类的实例化对象会发生什么:
PropertyInfo propInfo = b.GetType().GetProperty("TestString");
propInfo.CanRead ---> true
propInfo.CanWrite ---> false(!)
如果我尝试从反射调用 setter:
propInfo.SetValue("test", b, null);
我什至会收到带有以下消息的ArgumentException:
找不到属性集方法。
这符合预期吗?因为我似乎没有为 GetProperty() 方法找到 BindingFlags 的组合,该方法将属性与来自反射的有效 get/set 对返回给我。
编辑:
如果我在GetProperties() 上使用BindingFlags.DeclaredOnly,我会期望这种行为,但默认值 (BindingFlags.Default) 会考虑继承的成员,并且 TestString 的设置器显然是继承的!
【问题讨论】:
-
首先你错过了 A 类 oroperty 上的“虚拟”。然后,您已经覆盖了一个属性,该属性现在在 B 中不再具有设置器。我发现绑定标志不允许在只读属性上设置非常直观。
-
@Marino:我认为 OP 的观点是你可以合法地做
var b = new B(); b.TestString = "foo";但反射会告诉你B.TestString没有二传手。在这方面,GetProperty的行为似乎与GetMethod等不同。 -
@LukeH 我无法做到
var b = new B(); b.TestString = "foo";。它告诉我(正确地)属性 TestString 无法分配,因为它是只读的。我可以做A b = new B(); b.TestString = "foo";,但那是因为我将B 存储为A,而A 可以设置TestString属性。它实际上并没有做任何事情,因为在获取值时,它读取的是B.get_TestString(),而不是A.get_TestString() -
@LukeH 我复制/粘贴了原始问题中的类定义,除了我将
virtual添加到TestString属性定义中,因为否则它不会编译。是的,我确信它不会编译 :) 如果这很重要,我正在使用 .Net 4.0、VS 2010 和 Windows 7。 -
在 LinqPad 中为我编译。 nopaste.info/43c3ee3bde_nl.html 但正如预期的那样,如果我删除
override,它不会编译,隐藏而不是覆盖属性。
标签: c# .net reflection properties overriding