73

Under a given namespace, I have a set of classes which implement an interface. Let's call it ISomething. I have another class (let's call it CClass) which knows about ISomething but doesn't know about the classes which implement that interface.

I would like that CClass to look for all the implementation of ISomething, instantiate an instance of it and execute the method.

Does anybody have an idea on how to do that with C# 3.5?

GEOCHET
  • 21,119
  • 15
  • 74
  • 98
Martin
  • 39,309
  • 62
  • 192
  • 278
  • 2
    possible duplicate of [Getting all types that implement an interface with C# 3.0](http://stackoverflow.com/questions/26733/getting-all-types-that-implement-an-interface-with-c-sharp-3-0) – Keith Pinson Mar 10 '14 at 23:59

6 Answers6

140

A working code-sample:

var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
                where t.GetInterfaces().Contains(typeof(ISomething))
                         && t.GetConstructor(Type.EmptyTypes) != null
                select Activator.CreateInstance(t) as ISomething;

foreach (var instance in instances)
{
    instance.Foo(); // where Foo is a method of ISomething
}

Edit Added a check for a parameterless constructor so that the call to CreateInstance will succeed.

Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • 9
    Tiny clean up suggestion -- use Type.EmptyTypes instead of instantiating a new empty Type array. – Dustin Campbell Mar 31 '09 at 03:11
  • Is there a way to do this across all loaded assemblies? – gregmac Oct 21 '09 at 17:30
  • 14
    nevermind.. var instances = from assembly in AppDomain.CurrentDomain.GetAssemblies() from t in assembly.GetTypes() where t.GetInterfaces().Contains(typeof(ISomething)) && t.GetConstructor(Type.EmptyTypes) != null select Activator.CreateInstance(t) as ISomething; – gregmac Oct 21 '09 at 21:22
  • Nice! I haven't had to try that since I started using MEF. :) – Matt Hamilton Oct 21 '09 at 22:44
  • +1: I have a code snippet that just uses old-school reflection, but this is much nicer. – Brian MacKay Jul 15 '10 at 16:43
  • +1 Matt - a well late tick for this one. i particularly like the combination of this along with gregmac's addition, works great – jim tollan Feb 01 '11 at 19:42
11

You can get a list of loaded assemblies by using this:

Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()

From there, you can get a list of types in the assembly (assuming public types):

Type[] types = assembly.GetExportedTypes();

Then you can ask each type whether it supports that interface by finding that interface on the object:

Type interfaceType = type.GetInterface("ISomething");

Not sure if there is a more efficient way of doing this with reflection.

Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
Mitch Denny
  • 2,095
  • 13
  • 19
9

A example using Linq:

var types =
  myAssembly.GetTypes()
            .Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
3
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
    if (t.GetInterface("ITheInterface") != null)
    {
        ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
        executor.PerformSomething();
    }
}
Kiran
  • 31
  • 1
2

You could use something like the following and tailor it to your needs.

var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();

foreach (var type in types)
{
    if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
    {
        ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
        something.TheMethod();
    }
}

This code could use some performance enhancements but it's a start.

Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
0

Maybe we should go this way

foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() ) 
   instance.Execute(); 
bane 975
  • 87
  • 1
  • 7