我不确定解决这个问题的最佳方法,无论是通过反思,完全重新设计我的课程,还是做一些简单的事情。
基本上我有一个基类,我可以有任意数量的继承它的子类。让我们调用基类Shape和子类CircleShape,RectangleShape等
基类永远不会自己实例化,只有子类。有些从未实例化,有些在整个项目的生命周期中被多次实例化。
在我实例化之前,有时我需要特定于子类的信息。现在我使用枚举来区分所有子类类型。我在switch语句中基于枚举实例化每个子类,如下所示:
switch (shapeType)
{
case CircleShape:
shape = new CircleShape();
case SquareShape:
shape = new RectangleShape();
}
但是说我不想使用这种硬编码的switch语句,而是想通过所有子类进行枚举。有没有办法自动检索子类列表并访问其STATIC成员以获取有关它们的信息(在实例化之前)?或者更容易手动实例化每个类一次并将它们添加到数组中,以便我通过它们进行枚举(但不将这些实例与任何实际数据联系起来)。
或者我应该做一些完全不同的事情?
答案 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));
}
}
}
}
当然你也可以使用属性而不是静态成员,如果你想用你想要在运行时查找的信息来装饰类,那么这可能是最好的。有很多关于属性如何在互联网上运作的例子。