views:

128

answers:

4

I have a small project that I'm making, and I'm trying to figure out if it's possible to get an instance of every class that inherits from a particular interface.

Here's a simplified example of what I'm trying to accomplish:

public interface IExample
{
    string Foo();
}

public class Example1 : IExample
{
    public string Foo()
    {
        return "I came from Example1 !";
    }
}

public class Example2 : IExample
{
    public string Foo()
    {
        return "I came from Example2 !";
    }
}

//Many more ExampleN's go here

public class ExampleProgram
{

    public static void Main(string[] args)
    {
        var examples = GetExamples();

        foreach (var example in examples)
        {
            Console.WriteLine(example.Foo());
        }
    }

    public static List<IExample> GetExamples()
    {
        //What goes here?
    }
}

Is there any way (short of hard-coding it) for the GetExamples method to return a list containing an instance of each class inheriting from the interface IExample? Any insight you can give would be much appreciated.

+2  A: 

See: http://stackoverflow.com/questions/457676/c-reflection-check-if-a-class-is-derived-from-a-generic-class

Also: http://stackoverflow.com/questions/80247/implementations-of-interface-through-reflection (this may be exactly what you want)

You will basically just need to enumerate through every type in the target assembly and test to see if it implements the interface.

routeNpingme
That second links answers your question, but it (obviously) only knows about types of assemblies you have loaded. So if you are making a library type class, you may not know about everything that implements your interface.
Tom Ritter
The second link was what I was looking for in terms of finding the types that implement that interface. The latter half of Matt Kellogg's answer below demonstrates how the objects would then be created. I wish I could mark both answers as correct :PThanks for the help!
A: 

You will have to use reflection.

Assembly.GetExecutingAssembly should be your starting point.

EDIT: Code that should help

Type[] types = Assembly.GetExecutingAssembly().GetTypes();
foreach(Type tp in types)
{
 if (typeof(IExample).IsAssignableFrom(tp))
 {
  if (tp.IsInterface == false)
  {
   IExample t = Activator.CreateInstance(tp) as IExample;
   Console.WriteLine(t.Foo());
  }
 }
}
shahkalpesh
A: 

Here's how I'd do something like that:

    public static List<IExample> GetExamples()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var types = assembly.GetTypes().Where(t => t.GetInterfaces().Any(i => i == typeof(IExample))).ToList();

        List<IExample> returnMe = new List<IExample>();
        foreach (var type in types)
            returnMe.Add((IExample) Activator.CreateInstance(type));

        return returnMe;
    }
Matt Kellogg
routeNpingme responded first with how to get the types that inherit from a given interface, but you demonstrated how to then return concrete instances of those types. I wish I could mark both answers as correct :P Thanks for the help!
+1  A: 

Building upon Matt's solution, I would implement it something like this:

public static List<IExample> GetExamples()
{
    return GetInstances<IExample>().ToList();
}

private static IEnumerable<T> GetInstances<T>()
{
    return Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => type.IsClass &&
                       !type.IsAbstract &&
                       type.GetConstructor(Type.EmptyTypes) != null &&
                       typeof (T).IsAssignableFrom(type))
        .Select(type => (T) Activator.CreateInstance(type));
}

This solution skips types that cannot be instantiated such as abstract classes, derived interfaces and classes without default (parameterless) public constructors.

Nathan Baulch