0

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
Nature GPL_
  • 3
  • 1
  • 3
  • 1
    Have you read the error? It's giving you a pretty major hint! It looks like you have a class that inherits from `ICommand` that is an abstract class which can not be created. You probably just need to test whether the class you are attempting to create is abstract or not `type.GetTypeInfo().IsAbstract;` – Mark Davies Mar 11 '20 at 09:32
  • At least one of the types you are trying to create an instance of is abstract. Abstract types can only be inherited from, they can not be instantiated. You could try printing each type you're trying to instantiate and see which one's causing the exception – Rupti Mar 11 '20 at 09:34
  • nobody ever reads exception messages :( _"Cannot create an abstract class"_ means that you can't create an instance of **abstract** class – vasily.sib Mar 11 '20 at 09:35

4 Answers4

8

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • `just like you can't do it with regular code` I think you mean directly. Please see https://stackoverflow.com/a/5602284/1985541 – Zuzlx Mar 11 '20 at 22:16
  • @Zuzlx: Well, I mean "of precisely that type rather than a derived type". – Jon Skeet Mar 12 '20 at 06:47
1

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));
Shai Aharoni
  • 1,955
  • 13
  • 25
0

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

Hiran
  • 1,102
  • 11
  • 18
  • 1
    It's not necessarily because it does not contain complete implementation. Abstract classes may be completely implemented (unlike interfaces) – Rupti Mar 11 '20 at 09:38
  • yes it may have, and this has been discussed before https://stackoverflow.com/questions/13670991/can-we-instantiate-an-abstract-class – Hiran Mar 11 '20 at 09:46
0

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.

Tom Ruyter
  • 176
  • 2
  • 9