在派生类中声明与基类中的属性名称匹配的属性“隐藏”它(除非它使用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()
只会返回B.P和C.P.是否可以以返回所有三种方式调用GetProperties()
?通过遍历继承层次结构几乎可以肯定有一种方法,但是有更清晰的解决方案吗?
答案 0 :(得分:6)
GetProperties被定义为该类型的所有公共属性。
您可以使用以下方式获取他们的get和set方法:
typeof(C).GetMethods()
.Where(m => m.Name.StartsWith("set_") || m.Name.StartsWith("get_"))
虽然这似乎是一个坏主意,但与继承层次结构相比,获取属性。
答案 1 :(得分:5)
我认为没有遍历继承层次结构是不可能的。不过,它不需要太多代码:
public static IEnumerable<PropertyInfo> 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;
}
}
当然,如果您知道一个共同的基本类型,您可以停止,而不是对象,它将更有效。也;这需要一些时间来进行反射,因此缓存结果。毕竟,类型信息在执行期间不会改变。
答案 2 :(得分:3)
通过反射,只有签名匹配时,new关键字才会隐藏继承的属性。我猜反射匹配属性访问器(get_&amp; set_)上的签名。这就是为什么GetProperties()
在返回类型不同时返回B.P和C.P的原因。
我最近发现Fasteflect提供了高级反射机制。
我检查了并且Fasteflect type.Properties
返回隐藏成员的所有树(P)。我认为API会考虑以不同方式支持成员(虚拟/覆盖)和隐藏成员(新成员),这对您的“问题”是一件好事;)
我用quickflect进行测试:
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)
[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