【问题标题】:Unity IoC for resolving assemblies dynamically用于动态解析程序集的 Unity IoC
【发布时间】:2012-03-07 03:52:55
【问题描述】:

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

我们的代码

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
}

}

【问题讨论】:

  • 这是 MEF 的主要用例之一,您可以考虑将它用于应用程序的插件部分(同时保留 Unity 以满足您的 IoC 需求。)跨度>
  • 这不是 Unity 或其他 IoC 框架的设计目标。因此,如果您愿意,请按照@dlev 的建议坚持使用 MEF。
  • @LexLi 我不同意这不是 DI 容器工作的一部分。它们旨在组装松散耦合的应用程序。这与加载插件并将它们添加到应用程序有什么不同?
  • @SebastianWeber,或者我应该说“简单”的容器,因为 MEF 列在复杂的下面,en.wikipedia.org/wiki/Dependency_injection
  • @LexLi 而一个简单的容器是......? Funq 之类的东西主要是为在移动/嵌入式场景中使用而设计的?

标签: c# inversion-of-control unity-container


【解决方案1】:

您可以编写一些反射代码来扫描文件夹中的插件程序集并将所有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);

(代码可能无法编译)

【讨论】:

  • 可以在TecX project on codeplex 中找到它的实现。它是 Unity 增强配置引擎的一部分。请参阅 TecX.Unity.Configuration
  • 感谢这帮助我开始工作。但是,请注意IsAssignableFrom(t) 将为类和接口返回true,因此您可能希望在迭代类型时添加对IsClass 的检查。此外,通过在 container.RegisterType() 方法调用中不指定注册名称,您正在用下一个注册覆盖每个先前的注册(导致只有一个注册类型),因此向 register 方法添加另一个参数,为您注册的每种类型添加一个唯一名称为t.FullName,以便可以注册实现IPlugin的多种类型。
【解决方案2】:
    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());
    });

如果有人仍然关心,这就是我动态加载实现特定接口 (ICommonWorker) 的 DLL 所做的。

【讨论】:

  • 小心使用 getfiles,因为即使单个文件存在读取访问问题,它也会引发异常。否则,这也是我使用 AutoFac 的方式。 Autofac 具有要继承的模块,您也可以将其用作标记。 devkimchi.com/631/dynamic-module-loading-with-autofac
猜你喜欢
  • 2014-01-22
  • 2012-10-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多