views:

591

answers:

2

I have got some code to load an assembly and get all types, which implement a certain interface, like this (assume asm is a valid and loaded assembly).

var results = from type in asm.GetTypes()
  where typeof(IServiceJob).IsAssignableFrom(type)
  select type;

Now I'm stuck: I need to create instances of these objects and invoke methods and properties on the object. And I need to store the references to the created objects in an array for later usage.

+5  A: 

Oh wow - I only blogged about this a few days ago. Here's my method to return instances of all the types that implement a given interface:

private static IEnumerable<T> InstancesOf<T>() where T : class
{
    var type = typeof(T);
    return from t in type.Assembly.GetExportedTypes()
           where t.IsClass
               && type.IsAssignableFrom(t)
               && t.GetConstructor(new Type[0]) != null
           select (T)Activator.CreateInstance(t);
}

If you refactor this to accept an assembly parameter rather than using the interface's assembly, it becomes flexible enough to suit your need.

Matt Hamilton
That's some crazy LINQ there man. ;)
Chad Grant
@Matt Hamilton: is it possible then to invoke a constructor in such a way of there is no default empty constructor?
towps
Activator.CreateInstance has an overload which can accept an array of objects that are passed to the ctor of the class you're instantiating, but I don't think there's any way you could use that within a single query like the one I've posted here.
Matt Hamilton
+1  A: 

You can create an instance of a type with the Activator.CreateInstance method:-

IServiceJob x = Activator.CreateInstance(type);

So your code becomes:-

IServiceJob[] results = (from type in asm.GetTypes()
  where typeof(IServiceJob).IsAssignableFrom(type)
  select (IServiceJob)Activator.CreateInstance(type)).ToArray();

(Note change var to IServiceJob[] to make it clear what is being created).

AnthonyWJones
Keep in mind that if the implementing type doesn't have a default ctor, this code will throw a MethodMissingException. Hence the check in my query.
Matt Hamilton
@Matt Hamilton: is it possible then to invoke a constructor in such a way of there is no default empty constructor?
towps