使用 Activator.CreateInstance 方法检索的(集合的)元素的类型是什么?

What is the type of element (of a collection) which retrieve from using Activator.CreateInstance method?

我有一个案例和下面的案例很相似:

Get all inherited classes of an abstract class

我有两个 classes 继承了一个基数 class

这是我的基地class:

public abstract class InputModule
{
      public string ModuleName;
      public int NumberOfInputFields;
}

这是第一个继承class:

public class Module1 : InputModule
{
      new public string  ModuleName = "FilmMusic";
      public new int NumberOfInputFields = 7;
}

秒:

public class Module2 : InputModule
{
      new public string ModuleName = "MovieStaffInfo";
      public new int NumberOfInputFields = 4;
}

我想获取 ModuleName 的值:"FilmMusic" 和 "MovieStaffInfo"。

有了这个值,在用户进入主窗体之前,我可以向主窗体添加一个新的 UI(UI 用于 FilmMusic 模块,另一个 UI 用于 MovieStaff)。

下面是我用过的代码(大部分是指我上面提到的案例):

public void detectTotalNumberOfSector()
{
     IEnumerable<InputModule> exporters = typeof(InputModule).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(InputModule)) && !t.IsAbstract).Select(t => (InputModule)Activator.CreateInstance(t));
     foreach (var item in exporters)
     {
         Console.WriteLine(item.ModuleName);   
     } 
}

我得到了输出"null, null"

然后我在 foreach 循环中添加了这些代码:

FieldInfo info = item.GetType().GetField("ModuleName"); 
Console.WriteLine(info.GetValue(item));

我得到了我想要的"FilmMusic, MovieStaffInfo"。

我有点困惑,导出器集合中的元素是什么?

一开始我猜item是class Module1, Module2...的一个实例,所以我可以用item.ModuleName来访问 ModuleName 的值。

其实我不能,我必须使用FieldInfoGetValue来访问字段值,但也很奇怪,因为使用GetValue我必须创建首先作为参数分配给 GetValue 的实例化(在我的例子中,item 是 class Module1,Module2 的实例化......我猜) .

那么,集合导出器的项目是否是class模块1、模块2的实例?

如果是,为什么我在使用 item.ModuleName 时得到 null?

谢谢大家的意见~

您已经使用 new 关键字定义了 ModuleName(例如 new public string ModuleName)。这意味着如果指向实例的变量被键入为基础 class,它将无法看到 "new" 字段。

如果您希望能够看到模块名称,您有两个选择。

  1. 删除 new 关键字。相反,将该成员声明为覆盖,例如

    public override string ModuleName = "etc."; 
    
  2. 使用反射调用派生类型上的字段,例如

    Console.WriteLine
    (
        item.GetType()
            .GetField("ModuleName", BindingFlags.Instance | BindingFlags.Public)
            .GetValue(item)
    );
    

另见 Difference between new and overrride

个人推荐第一种。需要 new 关键字是不常见的。