简体   繁体   中英

System.MissingMethodException: Cannot create an abstract class

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 inherited ICcommand But why is there an error?

Error

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

But why is there an error?

Because you're trying to create an instance of an abstract class (rather than a concrete class derived from that abstract class). You can't do that with reflection, just like you can't do it with regular code. If you were to try writing code of var command = new FooCommand(); (where FooComand is the type that it's failing on) that code would fail to compile.

Your code for checking which types to instantiate should include !p.IsAbstract to filter out abstract classes that implement ICommand .

The error tells you exactly what is wrong. You can't create an instance of an abstract class.

You need to filter your types so that they don't include abstract types. like this:

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

You cannot create a instance of both abstract class and interface. Because it does not contain complete implementation. So, first implement it.

See this Microsoft Doc For Reference

Like most abstract class implementation in most languages, you can't create an object of that specifically. It's used as a building block, typically for common code shared amongst other classes.

The Execption is correct. When you loaded your classes / objects by reflection using the interface as it's identifier, one of the classes that implemented that interface is abstract and can't be instanciated with Activator.CreateInstance , but your code doesn't know that until runtime as it can do type checking on stuff created dynamically at runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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