根据文档使用时无法从 Mef CompositionContainer 解析 Autofac 依赖项
Unable to resolve Autofac dependencies from a Mef CompositionContainer when used according to documentation
根据 http://docs.autofac.org/en/latest/integration/mef.html.
上的文档使用时,Mef CompositionContainer
无法解析 Autofac 依赖项
我有一个大型代码库,它广泛使用了 ServiceLocator 和单例...服务定位器通过使用缓存 System.ComponentModel.Composition.Hosting.CompositionContainer
来完成所有对象创建、组合等。 (另请注意,我们目前 use/need 元数据支持)我正在尝试从这个切换到更现代的架构。为此,现有的基于 Mef(基于“CompositionContainer”)的服务定位器必须与 Autofac IoC 容器合作。
下面的函数
- 创建一个 Mef
CompositionContainer
- 证明 MEF 能够解决简单的导出问题
- 配置 Autofac 以使用
.Exported
扩展方法向 MEF 注册并导出 AutofacExport
到 MEF。
- 证明 Autofac 可以解析具有 Autofac 中定义的依赖项的 mef 组件
- 说明 Mef 无法解析具有 Autofac 依赖项的导出组件组件。
抛出的异常为:ImportCardinalityMismatchException("No exports were found that match the constraint: ContractName MefExportWithDependency RequiredTypeIdentity MefExportWithDependency"
抛出。
public void MefResolve_ObjectWithDependency_CanResolveWhenAutofacRegistersDependeyncy2()
{
//1. Initialize Mef
var composablePartCatalogs = new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
//A lot more here..
};
var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);
var container = new CompositionContainer(aggregateCatalog, true);
//2. As expected this is resolved
container.GetExport<MefExport>().Should().NotBeNull();
//3. Initialize Autofac
var builder = new ContainerBuilder();
builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>());
builder.RegisterComposablePartCatalog(aggregateCatalog);
var ioc = builder.Build();
//4. Here Autofac is correctly providing the dependency to the mef ImportingConstructor
ioc.Resolve<MefExportWithDependency>().AutofacExport.Should().NotBeNull();
//5. The next line will throw ImportCardinalityMismatchException
container.GetExport<MefExportWithDependency>();
}
上面的代码需要定义以下 类:
public class AutofacExport { }
[Export]
public class MefExport { }
[Export]
public class MefExportWithDependency
{
public AutofacExport AutofacExport { get; set; }
[ImportingConstructor]
public MefExportWithDependency(AutofacExport autofacExport)
{
AutofacExport = autofacExport;
}
}
注意:
我也看过 https://www.nuget.org/packages/MefContrib.Integration.Autofac/ - 它承诺将 Mef 与 Autofac 集成。但是,我没能找到有关如何配置的相关文档,而且该软件包的用途也不多。
我认为您可能误解了 Autofac.Mef 包的工作方式。虽然它将 MEF 项目引入 Autofac,让 Autofac 了解 export/import 属性和在 MEF 目录中注册的项目,这是一种单向操作 - 它不会将 Autofac 注册推入 MEF 或允许MEF CompositionContainer
使用 Autofac.
我相信您想要的是您提到的 MefContrib.Integration.Autofac 程序包,它似乎允许事情从另一个方向流动 - 从 Autofac 到 MEF。
查看其工作原理的好地方是他们的存储库,他们在其中 some unit tests 显示了 MEF 正在解析 Autofac 项目的集成。这是一个这样的测试:
[Test]
public void ExportProviderResolvesServiceRegisteredByTypeTest()
{
// Setup
var builder = new ContainerBuilder();
builder.RegisterType<AutofacOnlyComponent1>().As<IAutofacOnlyComponent>();
var autofacContainer = builder.Build();
var adapter = new AutofacContainerAdapter(autofacContainer);
var provider = new ContainerExportProvider(adapter);
var component = provider.GetExportedValue<IAutofacOnlyComponent>();
Assert.That(component, Is.Not.Null);
Assert.That(component.GetType(), Is.EqualTo(typeof(AutofacOnlyComponent1)));
}
如您所见,他们有一个适用于 Autofac 容器的适配器,可以将它们 "converts" 转换为 MEF 可以理解的内容。他们还有 some unit tests showing bi-directional integration - MEF 从 Autofac 解析,Autofac 从 MEF 解析。
我个人从未使用过该软件包,但我认为,如果您查看测试以及他们如何设置这些测试,它应该会让您上路。
根据 http://docs.autofac.org/en/latest/integration/mef.html.
上的文档使用时,MefCompositionContainer
无法解析 Autofac 依赖项
我有一个大型代码库,它广泛使用了 ServiceLocator 和单例...服务定位器通过使用缓存 System.ComponentModel.Composition.Hosting.CompositionContainer
来完成所有对象创建、组合等。 (另请注意,我们目前 use/need 元数据支持)我正在尝试从这个切换到更现代的架构。为此,现有的基于 Mef(基于“CompositionContainer”)的服务定位器必须与 Autofac IoC 容器合作。
下面的函数
- 创建一个 Mef
CompositionContainer
- 证明 MEF 能够解决简单的导出问题
- 配置 Autofac 以使用
.Exported
扩展方法向 MEF 注册并导出AutofacExport
到 MEF。 - 证明 Autofac 可以解析具有 Autofac 中定义的依赖项的 mef 组件
- 说明 Mef 无法解析具有 Autofac 依赖项的导出组件组件。
抛出的异常为:ImportCardinalityMismatchException("No exports were found that match the constraint: ContractName MefExportWithDependency RequiredTypeIdentity MefExportWithDependency"
抛出。
public void MefResolve_ObjectWithDependency_CanResolveWhenAutofacRegistersDependeyncy2()
{
//1. Initialize Mef
var composablePartCatalogs = new List<ComposablePartCatalog>
{
new AssemblyCatalog(Assembly.GetExecutingAssembly())
//A lot more here..
};
var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);
var container = new CompositionContainer(aggregateCatalog, true);
//2. As expected this is resolved
container.GetExport<MefExport>().Should().NotBeNull();
//3. Initialize Autofac
var builder = new ContainerBuilder();
builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>());
builder.RegisterComposablePartCatalog(aggregateCatalog);
var ioc = builder.Build();
//4. Here Autofac is correctly providing the dependency to the mef ImportingConstructor
ioc.Resolve<MefExportWithDependency>().AutofacExport.Should().NotBeNull();
//5. The next line will throw ImportCardinalityMismatchException
container.GetExport<MefExportWithDependency>();
}
上面的代码需要定义以下 类:
public class AutofacExport { }
[Export]
public class MefExport { }
[Export]
public class MefExportWithDependency
{
public AutofacExport AutofacExport { get; set; }
[ImportingConstructor]
public MefExportWithDependency(AutofacExport autofacExport)
{
AutofacExport = autofacExport;
}
}
注意: 我也看过 https://www.nuget.org/packages/MefContrib.Integration.Autofac/ - 它承诺将 Mef 与 Autofac 集成。但是,我没能找到有关如何配置的相关文档,而且该软件包的用途也不多。
我认为您可能误解了 Autofac.Mef 包的工作方式。虽然它将 MEF 项目引入 Autofac,让 Autofac 了解 export/import 属性和在 MEF 目录中注册的项目,这是一种单向操作 - 它不会将 Autofac 注册推入 MEF 或允许MEF CompositionContainer
使用 Autofac.
我相信您想要的是您提到的 MefContrib.Integration.Autofac 程序包,它似乎允许事情从另一个方向流动 - 从 Autofac 到 MEF。
查看其工作原理的好地方是他们的存储库,他们在其中 some unit tests 显示了 MEF 正在解析 Autofac 项目的集成。这是一个这样的测试:
[Test]
public void ExportProviderResolvesServiceRegisteredByTypeTest()
{
// Setup
var builder = new ContainerBuilder();
builder.RegisterType<AutofacOnlyComponent1>().As<IAutofacOnlyComponent>();
var autofacContainer = builder.Build();
var adapter = new AutofacContainerAdapter(autofacContainer);
var provider = new ContainerExportProvider(adapter);
var component = provider.GetExportedValue<IAutofacOnlyComponent>();
Assert.That(component, Is.Not.Null);
Assert.That(component.GetType(), Is.EqualTo(typeof(AutofacOnlyComponent1)));
}
如您所见,他们有一个适用于 Autofac 容器的适配器,可以将它们 "converts" 转换为 MEF 可以理解的内容。他们还有 some unit tests showing bi-directional integration - MEF 从 Autofac 解析,Autofac 从 MEF 解析。
我个人从未使用过该软件包,但我认为,如果您查看测试以及他们如何设置这些测试,它应该会让您上路。