财产隐藏和反思(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
-