假设我有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)缺少一些简单的东西,但似乎无法了解它是什么。
这可能还是有解决方法?最终,我将进行全双向依赖注入和动态组件发现。
答案 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,您将获得例外。