【问题标题】:Unable to resolve Autofac dependencies from a Mef CompositionContainer when used according to documentation根据文档使用时,无法从 Mef CompositionContainer 解析 Autofac 依赖项
【发布时间】:2015-06-22 15:49:50
【问题描述】:

根据http://docs.autofac.org/en/latest/integration/mef.html 的文档使用时,Mef CompositionContainer 无法解析 Autofac 依赖项。

我有一个大型代码库,它广泛使用了 ServiceLocator 和单例...服务定位器通过使用缓存的 System.ComponentModel.Composition.Hosting.CompositionContainer 来完成所有对象创建、组合等。 (另外,请注意我们目前使用/需要元数据支持)我正在尝试从这个切换到更现代的架构。为此,现有的基于 Mef(基于“CompositionContainer”)的服务定位器必须与 Autofac IoC 容器合作。

下面的函数

  1. 创建一个 Mef CompositionContainer
  2. 证明 MEF 能够解析简单的导出
  3. 将 Autofac 配置为向 MEF 注册并使用 .Exported 扩展方法将 AutofacExport 导出到 MEF。
  4. 证明 Autofac 可以使用 Autofac 中定义的依赖关系解析 mef 组件
  5. 表明 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 集成。但是,我找不到有关如何配置它的相关文档,并且该软件包没有太多用途。

【问题讨论】:

    标签: c# mef autofac


    【解决方案1】:

    我认为您可能误解了 Autofac.Mef 包的工作方式。虽然它将 MEF 项目引入 Autofac,让 Autofac 了解在 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 容器的适配器,可以将它们“转换”成 MEF 可以理解的东西。他们还有some unit tests showing bi-directional integration - MEF 从 Autofac 解析,Autofac 从 MEF 解析。

    我从未亲自使用过该软件包,但我认为,如果您查看测试以及他们如何设置这些测试,它应该会让您顺利上路。

    【讨论】:

    • 谢谢! - 我担心这是单向操作。不幸的是,我在 Autofac 文档中没有找到任何表明这一点的东西。我将不得不进行更多分析,以检查添加(相当旧的)MefContrib 包是否有意义。
    • 我已更新文档以添加一些关于此的说明。修复的文档应该很快就会发布。
    • 谢谢@TravisIllig,如果一个类有一个 ImportingContructor 属性,那是否就不可能要求 Autofac 注册的另一个依赖项?即public myClass(IMefService mefService, IAutofacService afService)
    • 我不认为我理解这个问题。我推荐两件事:1)尝试一下。 2)如果您认为有些东西应该可以工作但没有,请使用您尝试过的代码以及您期望发生的情况打开一个新的 SO 问题。
    猜你喜欢
    • 2017-05-06
    • 1970-01-01
    • 2016-06-17
    • 2021-11-07
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多