gpt4 book ai didi

c# - 具有覆盖属性和反射的奇怪效果

转载 作者:可可西里 更新时间:2023-11-01 08:10:40 26 4
gpt4 key购买 nike

我在 .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:

Property set method not found.

这是预期的吗?因为我似乎没有为 GetProperty() 方法找到 BindingFlags 的组合,该方法通过反射返回具有有效 get/set 对的属性。

编辑:如果我在 GetProperties() 上使用 BindingFlags.DeclaredOnly,我会期望这种行为,但默认 (BindingFlags.Default) 将继承的成员带入account 和 TestString 的 setter 显然是继承的!

最佳答案

解决方法如下:

typeof(B).GetProperty("TestString")
.GetAccessors() // { B.get_TestString() }
.First() // B.get_TestString()
.GetBaseDefinition() // A.get_TestString()
.DeclaringType // typeof(A)
.GetProperty("TestString") // A.TestString: CanRead and CanWrite

这种方法应该相当稳健。如果您正在寻找非公共(public)访问器,则需要更加小心(BindingFlags)。

编辑:

请注意,这种方法不同于“硬编码”typeof(A).GetProperty("TestString")typeof(B).BaseType.GetProperty("TestString"),因为它找到了声明相关属性的实际原始类型。由于派生类型不可能(至少在 C# 中)添加新的访问器到被覆盖的属性,所以这个“原始”类型的属性声明应该包含所有相关的访问器。

关于c# - 具有覆盖属性和反射的奇怪效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8140298/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com