繁体   English   中英

C#,反射,继承和静态字段?

[英]C#, reflection, inheritence and static fields?

我有一个从抽象超类继承的类系列,该类由两个具体的类实现:

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总是返回“重命名我”而不是单个名称。

我很确定自己在这里做些愚蠢的事情,但是我不太确定该做什么。

你有两个问题。

首先,您的静态字段实际上不会做您想要做的事情。 AbstractFoo一个静态字段-没有单独的BarFoo.fooName静态字段。 因此,如果您有一堆子类,则最后一个子类进行类型初始化的情况都会在设置字段时“获胜”。

接下来,当您调用BarFoo.GetName实际上仅是对AbstractFoo.GetName的调用BarFoo不会被初始化,因此您不会看到设置了“漂亮名称”。

从根本上讲,我建议您重新设计代码。 我建议您使用属性装饰每个类。 这样一来,您根本就不会依赖于类型初始值设定项,也不需要为每种类型声明单独的静态成员。 唯一的缺点是该值必须为常数。

另一种选择是使用虚拟属性,然后将其覆盖子类中-尽管当然需要您创建每种类型的实例。

静态成员有一个副本。 在当前设置下,每个子类都将覆盖该副本,从而仅提供一个名称。 您需要在每个子类上创建一个静态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的静态成员,并让子类的静态初始值设定项向该Dictionary添加一些内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM