3

We are using unity as IoC. We came across unique problem. We have created interface called IPlugin. This interface is shared across various third party vendors to develop their own plug in based on this interface. These plug ins then fits into our system. Vendors will provide their plugs in as dll. What we want is , Using unity we want to resolve all assembly’s type which is implemented with IPlugin interface. I came to know that this is achievable via MEF export attribute, I am wondering whether this can be achieved via Unity using some short of extension.

Our code

Public interface IPlugin
{
    Void ProcessData();
} 

Public class DataProcessor
{
    Var pluginList = unityContainer.ResolveAssemblies<IPlugIn>()
/*
There is no such method in unity but what we want is scan all assemblies in bin folder and load all types which are inheriting from IPlugIn
*/
}

Vendor’s assembly

Public class AbcCompanyPlugIn : IPlugin
{
Void ProcessData()
{
// some code
}

}
Public class XyzCompanyPlugIn : IPlugin
{
Void ProcessData()
{
// some code
}

}
bhavesh lad
  • 1,242
  • 1
  • 13
  • 23
  • This is one of the main use-cases for MEF, and you might consider using it for the plug-in portion of your app (while keeping Unity for the rest of your IoC needs.) – dlev Mar 07 '12 at 03:59
  • It is not a design goal of Unity or other IoC frameworks. So if you want it, stick to MEF as @dlev suggests. – Lex Li Mar 07 '12 at 06:08
  • 1
    @LexLi I disagree that this is not part of the job of a DI container. They are designed to assemble loosely coupled applications. How is that different from loading plugins and adding them to an application? – Sebastian Weber Mar 07 '12 at 07:09
  • @SebastianWeber, or I should have said "simple" containers, as MEF is listed under complicated, http://en.wikipedia.org/wiki/Dependency_injection – Lex Li Mar 07 '12 at 08:43
  • @LexLi Whereas a simple container would be...? Something like [Funq](http://funq.codeplex.com) which was primarily designed for use in mobile/embedded scenarios? – Sebastian Weber Mar 07 '12 at 13:15

2 Answers2

5

You could write a bit of Reflection code that scans a folder for add-in assemblies and registers all IPlugin implementations with the container.

Something like this ought to work:

var assemblies = // read all assemblies from disk
var pluginTypes = from a in assemblies
                  from t in a.GetExportedTypes()
                  where typeof(IPlugin).IsAssignableFrom(t)
                  select t;

foreach (var t in pluginTypes)
    container.RegisterType(typeof(IPlugin), t);

(code may not compile)

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • An implementation of that can be found in the [TecX project on codeplex](http://tecx.codeplex.com). It comes as part of an enhanced configuration engine for Unity. See _TecX.Unity.Configuration_ – Sebastian Weber Mar 07 '12 at 07:07
  • 2
    Thanks this helped me get going. However, note that `IsAssignableFrom(t)` will return true for both classes and interfaces, so you might want to add a check for `IsClass` when iterating over types. Also by not specifying a registration name in your `container.RegisterType()` method call you are overwriting each previous registration with the next (resulting in only one registered type), so add another parameter to the register method with a unique name for each type you register such as `t.FullName` so that multiple types can be registered that implement `IPlugin`. – BenSwayne Feb 20 '13 at 21:27
4
    var assemblies = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "Worker*.dll").Select(f => Assembly.LoadFile(f)).ToArray<Assembly>();

    (from asm in assemblies
        from t in asm.GetExportedTypes()
        where typeof(ICommonWorker).IsAssignableFrom(t) && t.IsClass
        select t).ForEach(x =>
    {
        unityContainer.RegisterType(typeof(ICommonWorker), x, x.FullName, new ContainerControlledLifetimeManager());
    });

If anyone still cares, this is what I did to load DLL's dynamically which implemented a specific interface (ICommonWorker).

hwnd
  • 71
  • 3
  • Be careful with getfiles as it will throw an exception if even a single file has read access issues. Otherwise this is how I do it with AutoFac too. Autofac has Module to inherit from and you can use it as a marker too. http://devkimchi.com/631/dynamic-module-loading-with-autofac/ – Dasith Wijes Sep 16 '16 at 07:33