财产隐藏和反思(C#)

在派生类中声明与基类中的属性名称匹配的属性“隐藏”它(除非它使用override关键字覆盖它)。 如果类型不匹配,则Type.GetProperties()将返回基类和派生类属性。 但是,如果它们的类型匹配,则只会返回派生类的属性。 例如:

 class A { protected double p; public int P { get { return (int)p; } set { p = value; } } } class B : A { public new int P { get { return (int)p; } set { p = value; } } } class C : B { public new float P { get { return (float)p; } set { p = value; } } } 

调用typeof(C).GetProperties()只返回BP和CP是否可以以返回全部三种方式调用GetProperties() ? 几乎可以肯定,通过遍历inheritance层次结构可以实现这一目标,但是有更清晰的解决方案吗?

GetProperties定义为该类型的所有公共属性。

您可以使用以下方法获取get和set方法:

 typeof(C).GetMethods() .Where(m => m.Name.StartsWith("set_") || m.Name.StartsWith("get_")) 

虽然这似乎是一个坏主意,相比之下,inheritance层次结构获取属性。

我不认为没有遍历inheritance层次结构是可能的。 但它不必太多代码,但是:

  public static IEnumerable GetAllProperties(Type t) { while (t != typeof(object)) { foreach (var prop in t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)) yield return prop; t = t.BaseType; } } 

当然,如果你知道一个共同的基本类型,你可以停止,而不是对象,它将更有效。 也; 这需要一些时间来进行reflection,因此缓存结果。 毕竟,类型信息在执行期间不会改变。

通过reflection,如果签名匹配,new关键字仅隐藏inheritance的属性。 我猜reflection匹配属性访问器(get_&set_)上的签名。 这就是GetProperties()在返回类型不同时返回BP和CP的原因。

我最近发现了Fasteflect ,它提供了先进的reflection机制。

我检查了Fasteflect type.Properties返回隐藏成员的所有树(P)。 我认为API会考虑以不同方式支持成员(虚拟/覆盖)和隐藏成员(新成员),这对您的“问题”是一件好事;)

我用更快的reflection测试:

 class Class1 { public object field1 = null; public virtual object Property1 { get; set; } public object Property2 { get; set; } public string Property3 { get; set; } } class Class2 : Class1 { public new object field1 = null; public override object Property1 { get; set; } public new string Property3 { get; set; } } class Class3 : Class2 { public new string Property3 { get; set; } } 

过滤后备成员但返回所有隐藏成员:

 typeof(Class3).Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Instance) 
  • typeof(Class3).Properties(Flags.ExcludeBackingMembers | Flags.Public | Flags.Instance)Count = 5 System.Collections.Generic.IList
    • [0] {System.String Property3} System.Reflection.PropertyInfo
    • [1] {System.Object Property1} System.Reflection.PropertyInfo
    • [2] {System.String Property3} System.Reflection.PropertyInfo
    • [3] {System.Object Property2} System.Reflection.PropertyInfo
    • [4] {System.String Property3} System.Reflection.PropertyInfo