如何使用MefContrib或其他技术将N个MEF导出注入到一个Unity复合服务中

本文关键字:一个 服务 复合 Unity 注入 其他 MefContrib 何使用 技术 MEF | 更新日期: 2023-09-27 18:10:48

假设我有以下5个独立的程序集(假设每个类的名称不同):

[Export(typeof(IService))]
public class Service: IService
{
    // ...
}

在我的主程序集中有一个类是这些的组合

public class CompositeService : IService
{
    public CompositeService(IEnumerable<IService> services)
    {
        // ...
    }
}

我想做的是让Unity容器为IService解析CompositeService,并为Unity提供MefContrib扩展,并找到其他5个出口并将它们注入CompositeService的构造函数。

问题是你不能有N实例对于一个无名的unityContainer.RegisterType<IService>,你也不能为命名的实例,如果他们都有相同的名称。

我想我错过了一些简单的结合两种技术(Unity + MEF)通过第三(MefContrib),但似乎不能拿起它是什么。

这是可能的还是有一个解决方案?最后,我将全面介绍双向依赖注入和动态组件发现。

如何使用MefContrib或其他技术将N个MEF导出注入到一个Unity复合服务中

我认为最好的方法可能是把它颠倒过来。而不是试图通过Unity注册你的组件,你实际上把这些部件的发现留给MEF。MEFContrib包含一个Unity集成机制,允许你的MEF组成部分被注入到Unity组件中。这是在Piotr WŁodek的博客上的原始细节,他也给了你一个样本。基本上,它的工作方式是您可以在UnityContainer上使用一系列扩展方法来注册您的目录。在内部,它将创建适当的扩展并连接容器。

下面是一个简单的例子,我们将创建一些接口:
public interface IUnityComponent
{
  IEnumerable<IMefComponent> MefComponents { get; }
}
public interface IMefComponent
{
  string Name { get; }
}

然后是一些我们将导出的样本部件(通过MEF):

[Export(typeof(IMefComponent))]
public class MefComponent1 : IMefComponent
{
  public string Name { get { return "MEF Component 1"; } }
}
[Export(typeof(IMefComponent))]
public class MefComponent2 : IMefComponent
{
  public string Name { get { return "MEF Component 2"; } }
}
现在,我们将创建另一个部分(这将通过Unity创建):
public class UnityComponent : IUnityComponent
{
  public UnityComponent(IEnumerable<IMefComponent> mefComponents) 
  { 
    // mefComponents should be provided from your MEF container.
    MefComponents = mefComponents;
  }
  public IEnumerable<IMefComponent> MefComponents { get; private set; }
}

将其全部连接起来,我们只需要在UnityContainer上使用RegisterCatalog扩展方法(在添加对MEFContrib的引用后导入MefContrib.Integration.Unity):

var container = new UnityContainer();
// Register the catalog - this handles MEF integration.
container.RegisterCatalog(new DirectoryCatalog("."));
// Register our Unity components.
container.RegisterType<IUnityComponent, UnityComponent>(new ContainerControlledLifetimeManager());
现在您应该能够获取实例并枚举mef提供的部分:
// Grab an instance of our component.
var instance = container.Resolve<IUnityComponent>();
foreach (var mefComponent in instance.MefComponents)
{
  Console.WriteLine(mefComponent.Name);
}

注释: 100%未经测试。

刚刚从Matthew那里尝试了相同的解决方案,它工作正常,Unity正在从MEF中提取出口并将它们注入构造函数(接受IEnumerable<>)。

不知道它是否能帮助你,但包括MefContrib和MefContrib. integration . unity可以帮助:有一段时间我只包括后者,遇到了类似的错误。

作为一个边注,请记住,所有的注册在Unity(来自MEF导出)将是"无名的",所以如果你尝试ResolveAll<>你会得到一个空的集合,如果你尝试Resolve<>你会得到一个异常,如果有超过1实现注册