以编程方式检索多个类的静态成员

时间:2011-09-09 19:52:16

标签: c# .net class reflection

我不确定解决这个问题的最佳方法,无论是通过反思,完全重新设计我的课程,还是做一些简单的事情。

基本上我有一个基类,我可以有任意数量的继承它的子类。让我们调用基类Shape和子类CircleShape,RectangleShape等

基类永远不会自己实例化,只有子类。有些从未实例化,有些在整个项目的生命周期中被多次实例化。

在我实例化之前,有时我需要特定于子类的信息。现在我使用枚举来区分所有子类类型。我在switch语句中基于枚举实例化每个子类,如下所示:

switch (shapeType)
{
case CircleShape:
    shape = new CircleShape();

case SquareShape:
    shape = new RectangleShape();
}

但是说我不想使用这种硬编码的switch语句,而是想通过所有子类进行枚举。有没有办法自动检索子类列表并访问其STATIC成员以获取有关它们的信息(在实例化之前)?或者更容易手动实例化每个类一次并将它们添加到数组中,以便我通过它们进行枚举(但不将这些实例与任何实际数据联系起来)。

或者我应该做一些完全不同的事情?

2 个答案:

答案 0 :(得分:4)

您可以使用属性在类上定义元数据,然后使用反射在运行时读取此元数据,以决定您要对此类执行的操作,而无需实例化它。

以下是有关使用属性的一些信息(您也可以创建自己的自定义属性)using attributes in C#

以下是一个快速示例:

课程定义:

   // ********* assign the attributes to the class ********

   [BugFixAttribute(121,"Jesse Liberty","01/03/05")]
   [BugFixAttribute(107,"Jesse Liberty","01/04/05", Comment="Fixed off by one errors")]
   public class MyMath
   {
   ...

使用Reflection阅读属性:

// get the member information and use it to retrieve the custom attributes
System.Reflection.MemberInfo inf = typeof(MyMath);
object[] attributes;
attributes = inf.GetCustomAttributes(typeof(BugFixAttribute), false);

// iterate through the attributes, retrieving the properties
foreach(Object attribute in attributes)
{
    BugFixAttribute bfa = (BugFixAttribute) attribute;
    Console.WriteLine("\nBugID: {0}", bfa.BugID);
    Console.WriteLine("Programmer: {0}", bfa.Programmer);
    Console.WriteLine("Date: {0}", bfa.Date);
    Console.WriteLine("Comment: {0}", bfa.Comment);
}

注意:请注意在大量对象的大量迭代中过度使用反射,因为它会带来显着的性能成本。

答案 1 :(得分:2)

您可以使用反射来枚举所有类,但这不是一种非常有效的方法,因为它有点慢。

如果他们都在同一个程序集中,你可以做类似的事情:

   class Shape
   {
      /* ... */
   }

   class CircleShape : Shape
   {
      public static string Name
      {
         get
         {
            return "Circle";
         }
      }
   }

   class RectangleShape : Shape
   {
      public static string Name 
      {
         get
         {
            return "Rectangle";
         }
      }
   }

   class Program
   {
      static void Main(string[] args)
      {
         var subclasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(Shape)));
         foreach (var subclass in subclasses)
         {
            var nameProperty = subclass.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
            if (nameProperty != null)
            {
               Console.WriteLine("Type {0} has name {1}.", subclass.Name, nameProperty.GetValue(null, null));
            }
         }
      }
   }

当然你也可以使用属性而不是静态成员,如果你想用你想要在运行时查找的信息来装饰类,那么这可能是最好的。有很多关于属性如何在互联网上运作的例子。