Type.GetProperties不从基本类型返回非虚拟的重新定义的属性

时间:2018-09-25 14:00:23

标签: c# reflection

我正在开发一个自定义序列化程序,我的边缘案例测试揭示了一个有趣的问题:Type.GetProperties方法不会从相同签名的基类中返回重新引入的属性。虽然这对于重写属性是预期的,但我必须序列化非虚拟基本属性。

考虑以下示例:

public class Base
{
    public int NonvirtualProperty { get; set; } // this property is "lost"
    public virtual int VirtualProperty { get; set; }
    public int BaseOnlyProperty { get; set; }
}

public class Derived : Base
{
    public int NonvirtualProperty { get; set; }
    public override int VirtualProperty { get; set; }
    public int DerivedOnlyProperty { get; set; }
}

下面的测试演示了该问题:

foreach (var p in typeof(Derived).GetProperties(BindingFlags.Public | BindingFlags.Instance))
    Console.WriteLine($"{p.DeclaringType.Name}.{p.Name}");

// Derived.NonvirtualProperty
// Derived.VirtualProperty
// Derived.DerivedOnlyProperty
// Base.BaseOnlyProperty

我希望结果也Base.NonvirtualProperty

注意:对于字段和方法,一切正常。这对于方法尤其有趣,因为它们也可以是虚拟的。

注意2::如果BaseDerived中的属性类型不同,则基本属性会出现在结果中。

什么是最好,最有效的解决方案?

到目前为止,我的想法(对于处理这种极端情况,它们都显得太丑陋和过于复杂):

  • 也许我可以通过DeclaredOnly绑定标志来获取每个级别的属性,并以某种方式检测它们是非虚拟属性还是虚拟属性的最衍生属性。有没有一种干净的方法可以做到这一点?
  • 或者我可以改为查询方法,并检查返回的get_* / set_*方法是否真的是属性。

2 个答案:

答案 0 :(得分:0)

Imho无法仅通过反映派生类型来获取隐藏的基本属性。遍历继承链应该可以解决问题。

编辑:该问题似乎与Property hiding and reflection (C#)类似 还有一个很好的示例,说明如何使用较少的代码进行遍历,请参阅https://stackoverflow.com/a/2715286/7895292

答案 1 :(得分:-1)

那是因为Derived.NonvirtualProperty隐藏了Base.NonvirtualProperty。就像编译器会说的那样。它会建议“如果打算隐藏则使用new关键字”


不能直接访问的证明:

var d = new Derived();

var b = (Base)d;

b.NonvirtualProperty =10;

Console.WriteLine($"{d.NonvirtualProperty}");

0