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