I have an interface IExample
, and a set of classes ClassOne
, ClassTwo
and ClassThree
, all defined in different namespaces. I will possibly remove either of the classes, or add a new one in a new place, at a later stage in development.
Now, I want to find all types that implement IExample
at runtime, and instantiate them. (I know on beforehand that no class implementing IExample
will ever need any constructor arguments, but I don't know how to specify that in code, so it's me - not the compiler - that knows...)
Is this possible? How do I go about to do it?
Update: I've now tried several of the approaches suggested, but on all of them, the line Activator.CreateInstance(type)
, I get a System.MissingMethodException because I "cannot create an instance of an interface." This is my code:
var tasks = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => typeof(IBootstrapperTask).IsAssignableFrom(t))
// This line is where it fails
.Select(t => Activator.CreateInstance(t) as IBootstrapperTask)
.ToArray();
new AutoMapperBootstrapper(tasks).Initialize();
Without the as
clause I don't see any exception, but I'm given an object[]
, and I need an IBootstrapperTask[]
for the constructor on the last line in the excerpt. I've tried various ways to cast it, but none seem to work.
An interface can't be instantiated directly. Its members are implemented by any class or struct that implements the interface. A class or struct can implement multiple interfaces. A class can inherit a base class and also implement one or more interfaces.
No, you cannot instantiate an interface. Generally, it contains abstract methods (except default and static methods introduced in Java8), which are incomplete. Still if you try to instantiate an interface, a compile time error will be generated saying “MyInterface is abstract; cannot be instantiated”.
Must we implement all the methods in a class that implements an interface in Java? Yes, it is mandatory to implement all the methods in a class that implements an interface until and unless that class is declared as an abstract class.
Note: A class can extend a class and can implement any number of interfaces simultaneously.
This can be done with Reflection. For example
var interfaceType = typeof(IExample);
var all = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => interfaceType.IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.Select(x => Activator.CreateInstance(x));
Note: This will only create instances of IExample
from assemblies loaded in the current AppDomain
. This can be different than all assemblies loaded in the current process. However for many types of applications this will be equivalent.
You'd need to know a list of assemblies to look in, but then LINQ makes it relatively easy:
var instances = (from assembly in assemblies
from type in assembly
where !type.IsAbstract &&
type.IsClass &&
type.IsPublic &&
!type.IsGenericType &&
typeof(IExample).IsAssignableFrom(type)
let ctor = type.GetConstructor(Type.EmptyTypes)
where ctor != null && ctor.IsPublic
select (IExample) Activator.CreateInstance(type))
.ToList();
You may think of some other restrictions to add, but they're pretty easy to express :)
instances
will then be a List<IExample>
.
EDIT: I suspect my code will work where yours didn't, because I'm specifically excluding non-classes. My guess is that your code is trying to instantiate the interface itself, i.e. when t
is typeof(IBootstrapperTask)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With