2012-03-07 55 views
2

我们使用unity作为IoC。我们遇到了独特的问题。 我们已经创建了名为IPlugin的接口。这个接口在不同的第三方供应商之间共享,基于这个接口开发他们自己的插件。这些插件然后适合我们的系统。 供应商将提供他们的插件作为DLL。我们想要的是, 使用统一性,我们想要解析所有使用IPlugin接口实现的程序集类型。我知道这是通过MEF导出属性实现的,我想知道这是否可以通过Unity使用一些短的扩展来实现。Unity IoC动态解析程序集

我们的代码

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 
*/ 
} 

供应商的组件

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

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

} 
+0

这是MEF的主要用例之一,您可以考虑将其用于应用程序的插件部分(同时让Unity保留其余的IoC需求)。 – dlev 2012-03-07 03:59:22

+0

这不是设计目标Unity或其他IoC框架。所以如果你想要它,就像@dlev所建议的那样坚持MEF。 – 2012-03-07 06:08:46

+1

@LexLi我不同意这不是DI容器工作的一部分。它们旨在组装松散耦合的应用程序。这与加载插件并将其添加到应用程序有何不同? – 2012-03-07 07:09:10

回答

5

你可以写一点思考代码扫描外接组件的文件夹,并用容器注册所有IPlugin实现。

像这样的东西应该工作:

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); 

(代码可能无法编译)

+0

可以在[codec]上的[TecX项目](http://tecx.codeplex.com)中找到它的实现。它是Unity的增强型配置引擎的一部分。请参阅_TecX.Unity.Configuration_ – 2012-03-07 07:07:33

+2

谢谢,这帮助我走了。但是,请注意'IsAssignableFrom(t)'将对类和接口都返回true,因此您可能需要在迭代类型时添加对“IsClass”的检查。另外,通过在'container.RegisterType()'方法调用中不指定注册名称,您将覆盖每个以前的注册(导致只有一个注册类型),因此需要为注册方法添加另一个参数,并为每个注册方法指定一个唯一的名称输入你注册的名字,比如't.FullName',这样就可以注册多个类型来实现'IPlugin'。 – BenSwayne 2013-02-20 21:27:15

3
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()); 
    }); 

如果现在还有人关心,这是我做的加载DLL的动态,其实现特定的接口(ICommonWorker)。

+0

请小心使用getfiles,因为即使单个文件存在读取访问问题,也会引发异常。否则,这就是我如何使用AutoFac来完成它。 Autofac有模块可以继承,也可以用它作为标记。 http://devkimchi.com/631/dynamic-module-loading-with-autofac/ – 2016-09-16 07:33:29