财产隐藏和反思(C#)

时间:2010-04-26 16:16:43

标签: c# .net reflection inheritance

在派生类中声明与基类中的属性名称匹配的属性“隐藏”它(除非它使用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()?通过遍历继承层次结构几乎可以肯定有一种方法,但是有更清晰的解决方案吗?

3 个答案:

答案 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) 
  • 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