Reputation: 3
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
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
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
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
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