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

本文关键字:静态成员 编程 方式 检索 | 更新日期: 2023-09-27 18:08:02

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

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

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

有时候,在实例化子类之前,我需要特定于子类的信息。现在我使用枚举来区分所有子类类型。我在switch语句中基于枚举实例化每个子类,如下所示:
switch (shapeType)
{
case CircleShape:
    shape = new CircleShape();
case SquareShape:
    shape = new RectangleShape();
}

但是,假设我不想使用这种硬编码的switch语句,而是想枚举所有的子类。是否有一种方法可以自动检索子类列表并访问它们的STATIC成员以获取有关它们的信息(在实例化它们之前)?或者手动实例化每个类一次,然后将它们添加到数组中,这样就可以枚举它们(但不将这些实例绑定到任何实际数据)。

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

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

您可以使用属性在您的类上定义元数据,然后在运行时使用反射来读取这些元数据,以决定您想要对该类做什么,而无需实例化它。

这里有一些关于在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
   {
   ...

使用反射读取属性:

// 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);
}

注意:要小心在大量对象的大量迭代中过多地使用反射,因为它会带来很大的性能成本。

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

如果它们都在同一个程序集中,你可以这样做:

   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));
            }
         }
      }
   }
当然,你也可以使用属性来代替静态成员,如果你想用你想在运行时查找的信息来修饰类,这可能是更可取的。在互联网上有很多关于属性如何工作的例子。