我有一系列继承自抽象超类的类,它由两个具体的类实现:
public abstract class AbstractFoo
{
protected static string fooName = "Reset me!";
public static string GetName()
{
return fooName;
}
}
然后构造类似
的子类public class BarFoo : AbstractFoo
{
static BarFoo()
{
fooName = "Pretty Name For BarFoo";
}
}
等等。
我希望获得所有AbstractFoo
实现的漂亮名称的列表,以便用户可以决定使用哪种实现。
我的反思代码看起来像
Type fooType = typeof(AbstractFoo);
List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));
foreach (Type thisType in fooTypes)
{
MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
string name = (string) method.Invoke (null, null);
// add to the list, anyhow names.Add (name);
}
我最终以method.Invoke
总是返回“重命名我”而不是个人名字。
我很确定我在做傻事,但我不太确定是什么。
答案 0 :(得分:4)
你有两个问题。
首先,你的静态领域真的不会做你想要的。在AbstractFoo
中有一个静态字段 - 没有单独的BarFoo.fooName
静态字段。因此,如果你有一堆子类,无论哪个子类进行类型初始化,最后都会在设置字段时“赢”。
接下来,当您调用BarFoo.GetName
时,那个真的只是对AbstractFoo.GetName
的调用 - BarFoo
将无法初始化,因此您将看不到正在设置“漂亮的名字”。
从根本上说,我建议你重新设计你的代码。我建议你用属性装饰每个类。这样你根本不会完全依赖于类型初始化器,并且你不需要为每种类型声明一个单独的静态成员。唯一的缺点是价值必须是一个常数......
另一种方法是使用一个虚拟属性,然后在子类中重写 - 当然,这需要您创建每种类型的实例。
答案 1 :(得分:2)
静态成员有一个副本。使用当前设置,每个子类都将覆盖该副本,从而导致只有一个名称可用。您需要在每个子类上创建一个静态GetName函数,并直接返回该名称。我会推荐以下内容:
public abstract class AbstractFoo
{
}
public class BarFoo : AbstractFoo
{
public static string GetName()
{
return "Pretty Name For BarFoo";
}
}
Type fooType = typeof(AbstractFoo);
List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));
foreach (Type thisType in fooTypes)
{
MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static);
string name = (string) method.Invoke (null, null);
// add to the list, anyhow names.Add (name);
}
另一种方法是将Dictionary
保留为AbstractFoo
中的静态成员,并让子类'static initializers为该字典添加内容。