Tuesday, March 1, 2011

How to work with an interface dynamically loaded from an assembly and invoke its members

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.

From stackoverflow
  • 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.

    Chad Grant : That's some crazy LINQ there man. ;)
    towps : @Matt Hamilton: is it possible then to invoke a constructor in such a way of there is no default empty constructor?
    Matt Hamilton : 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.
  • 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).

    Matt Hamilton : 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.
    towps : @Matt Hamilton: is it possible then to invoke a constructor in such a way of there is no default empty constructor?

0 comments:

Post a Comment