【问题标题】:How to define a static method in a superclass to get the properties of a subclass using reflection?如何在超类中定义静态方法以使用反射获取子类的属性?
【发布时间】:2013-01-20 14:32:34
【问题描述】:

我有一个类BaseClass,它有一个GetPropertyByDataMemberName 方法。此方法使用反射来获取具有指定名称的DataMemberAttribute 的属性。我想在BaseClass 中将其定义为静态方法,因此我不必在每个子类中定义它。

问题是,由于此方法使用反射来查找属性,我需要以某种方式获取当前的Type 以便调用GetProperties。由于是静态方法,无法调用GetType,所以不知道该怎么做!

abstract class BaseClass
{
    [DataMember(Name = "p1")]
    public int PropertyOne{ get; set; }

    public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
    {
        return GetType() // argh! can't call this statically!
            .GetProperties()
            .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
            .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
    }
}

为什么不让它成为非静态的呢?好吧,假设我有一个这样的子类:

class SubClassOne : BaseClass
{
    [DataMember(Name = "p2")]
    public string PropertyTwo { get; set; }
}

我希望能够做这样的事情:

static void Main(string[] args)
{
    // print property names
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p1").Name);   // should work
    Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p2").Name);   // should not work
    Console.WriteLine(SubClassOne.GetPropertyByDataMemberName("p1").Name); // should work
    Console.WriteLine(SubClassOne.GetPropertyByDataMemberName("p2").Name); // should work
}

我尝试让GetPropertyByDataMemberName 使用typeof(BaseClass),但这只能获取BaseClass 的属性,而不是任何子类。

public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
{
    return typeof(BaseClass)
        .GetProperties() // only gets properties of BaseClass
        .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
        .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
}

那么,该怎么做呢?

【问题讨论】:

    标签: c# .net inheritance reflection properties


    【解决方案1】:

    您可以使用泛型来实现这一点:

    public static PropertyInfo GetPropertyByDataMemberName<T>(string dataMemberName)
        where T : BaseClass
    {
        return typeof(T)
            .GetProperties()
            .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
            .Single(z => ((DataMemberAttribute)Attribute.GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
    }
    
    // Shortcut overload for properties on BaseClass.
    public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
    {
        return GetPropertyByDataMemberName<BaseClass>(dataMemberName);
    }
    

    你可以这样称呼它:

    static void Main(string[] args)
    {
        Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p1").Name);   // should work
        Console.WriteLine(BaseClass.GetPropertyByDataMemberName("p2").Name);   // should not work
        Console.WriteLine(BaseClass.GetPropertyByDataMemberName<SubClassOne>("p1").Name); // should work
        Console.WriteLine(BaseClass.GetPropertyByDataMemberName<SubClassOne>("p2").Name); // should work
    }
    

    【讨论】:

      【解决方案2】:

      试试这个:

      public static PropertyInfo GetPropertyByDataMemberName(string dataMemberName)
      {
          var st = new StackTrace();
      
          var type = ((System.Reflection.MemberInfo)(st.GetFrame(0).GetMethod())).ReflectedType;
          return type // argh! can't call this statically!
              .GetProperties()
              .Where(z => Attribute.IsDefined(z, typeof(DataMemberAttribute)))
              .Single(z => ((DataMemberAttribute)Attribute
                  .GetCustomAttribute(z, typeof(DataMemberAttribute))).Name == dataMemberName);
      }
      

      【讨论】:

        猜你喜欢
        • 2020-02-15
        • 2011-04-01
        • 2010-10-01
        • 2010-10-02
        • 2012-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多