【问题标题】:System.MissingMethodException: Cannot create an abstract classSystem.MissingMethodException:无法创建抽象类
【发布时间】:2020-03-12 14:47:36
【问题描述】:

ExtendedCommandManager.cs

var assembly = AppDomain.CurrentDomain.GetAssemblies();
var types = assembly.SelectMany(s => s.GetTypes()).Where(p => typeof(ICommand).IsAssignableFrom(p));
foreach (var type in types)
{
   source.Commands.Add((ICommand) Activator.CreateInstance(type)); 
}

return source; 

type继承ICcommand但是为什么会报错?

错误

Unhandled exception. System.MissingMethodException: Cannot create an abstract class.
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean wrapExceptions, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& hasNoDefaultCtor)
   at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type)
   at BASE.CommandControllers.ExtendedCommandManager.Load[T](T source) in D:\CLang\DicordProject\Discord\BASE\CommandControllers\ExtendedCommandManager.cs:line 16

【问题讨论】:

  • 你读过错误吗?它给了你一个非常重要的提示!看起来您有一个继承自 ICommand 的类,这是一个无法创建的抽象类。您可能只需要测试您尝试创建的类是否是抽象的type.GetTypeInfo().IsAbstract;
  • 您尝试创建实例的类型中至少有一种是抽象的。抽象类型只能被继承,不能被实例化。您可以尝试打印您尝试实例化的每种类型,并查看导致异常的类型
  • 没有人读过异常信息 :( "Cannot create an abstract class" 表示您无法创建 abstract 类的实例跨度>

标签: c#


【解决方案1】:

但是为什么会出现错误呢?

因为您正在尝试创建抽象类的实例(而不是从该抽象类派生的具体类)。你不能用反射来做到这一点,就像你不能用常规代码来做一样。如果您尝试编写var command = new FooCommand(); 的代码(其中FooComand 是它失败的类型),该代码将无法编译。

您用于检查要实例化哪些类型的代码应包含 !p.IsAbstract 以过滤掉实现 ICommand 的抽象类。

【讨论】:

  • just like you can't do it with regular code 我想你的意思是直接的。请看stackoverflow.com/a/5602284/1985541
  • @Zuzlx:嗯,我的意思是“正是那种类型,而不是派生类型”。
【解决方案2】:

该错误会告诉您确切的问题所在。您不能创建抽象类的实例。

您需要过滤您的类型,使它们不包含抽象类型。像这样:

var types = assembly.SelectMany(s => s.GetTypes()).Where(p => !p.IsAbstract && typeof(ICommand).IsAssignableFrom(p));

【讨论】:

    【解决方案3】:

    您不能同时创建抽象类和接口的实例。因为它不包含完整的实现。 所以,首先实现它。

    【讨论】:

    【解决方案4】:

    看到这个Microsoft Doc For Reference

    像大多数语言中的大多数抽象类实现一样,您不能专门创建一个对象。它用作构建块,通常用于在其他类之间共享的公共代码。

    执行是正确的。当您使用接口作为标识符通过反射加载类/对象时,实现该接口的类之一是抽象的,不能用Activator.CreateInstance 实例化,但是您的代码直到运行时才知道它可以对运行时动态创建的内容进行类型检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 1970-01-01
      • 2010-10-15
      相关资源
      最近更新 更多