如何使用MefContrib或其他技术将N MEF导出注入1 Unity组合服务?

时间:2011-10-06 18:43:26

标签: c# dependency-injection unity-container mef composite

假设我有5个单独的程序集,其中包含以下内容(假设每个类名不同):

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

我的课程将在我的主要课程

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

我想要做的是让Unity容器解析CompositeService的{​​{1}}并为Unity提供MefContrib扩展名,然后找到其他5个导出并将其注入IService的构造函数。

问题是,对于无名CompositeService,您不能拥有 N 个实例,如果它们都具有相同名称,您也无法使用命名实例。

我认为我在两种技术(Unity + MEF)的组合中通过第三种(MefContrib)缺少一些简单的东西,但似乎无法了解它是什么。

这可能还是有解决方法?最终,我将进行全双向依赖注入和动态组件发现。

2 个答案:

答案 0 :(得分:0)

我认为最好的方法是翻转它。您不必尝试通过Unity注册组件,而是将这些组件的发现留给MEF。 MEFContrib包含一个Unity集成机制,允许将MEF组成的部分注入Unity组件。这是Piotr WŁodek's blog的原始详细信息,他还提供了样本。实际上,它的工作方式是您可以在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; }
}

要将所有内容连接起来,我们只需在RegisterCatalog上使用UnityContainer扩展方法(在添加对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);
}

note :100%未经测试。

答案 1 :(得分:0)

刚刚尝试了Matthew的相同解决方案并且工作正常,Unity正在从MEF中获取导出并将它们注入构造函数(接受IEnumerable&lt;&gt;)。

不知道它是否可以帮助你,但包括MefContrib和MefContrib.Integration.Unity都可以提供帮助:有一段时间我只包含后者并遇到类似的错误。

作为旁注,请记住,Unity中的所有注册(来自MEF导出)都将是“无名”,因此如果您尝试ResolveAll&lt;&gt;你会得到一个空的集合,如果你尝试Resolve&lt;&gt;如果注册的实施次数超过1,您将获得例外。