Nature GPL_
Nature GPL_

Reputation: 3

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

Upvotes: 0

Views: 4638

Answers (4)

Jon Skeet
Jon Skeet

Reputation: 1502116

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.

Upvotes: 8

Tom Ruyter
Tom Ruyter

Reputation: 176

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.

Upvotes: 0

Hiran
Hiran

Reputation: 1180

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

Upvotes: 0

Shai Aharoni
Shai Aharoni

Reputation: 1957

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));

Upvotes: 1

Related Questions