项目
版本

Autofac 管理扩展框架 (MEF)

Autofac 的 MEF 集成允许您使用 管理扩展框架 在应用程序中暴露扩展点。

要在 Autofac 应用程序中使用 MEF,您必须引用 .NET 框架的 System.ComponentModel.Composition.dll 组件,并从 NuGet 获取 Autofac.Mef 包。

注意:这是一个单向操作 MEF 集成允许 Autofac 解决在 MEF 中注册的项,但不允许 MEF 解决在 Autofac 中注册的项。

在 Autofac 中使用 MEF 扩展

Autofac/MEF 集成允许将 MEF 目录注册到 ContainerBuilder,然后使用 RegisterComposablePartCatalog() 扩展方法。

var builder = new ContainerBuilder();
var catalog = new DirectoryCatalog(@"C:\MyExtensions");
builder.RegisterComposablePartCatalog(catalog);

支持所有 MEF 目录类型:

  • TypeCatalog
  • AssemblyCatalog
  • DirectoryCatalog

一旦注册了 MEF 目录,其中的导出项可以通过 Autofac 容器或注入到其他组件来解决。例如,假设您有一个使用 MEF 属性定义导出类型的类:

[Export(typeof(IService))]
public class Component : IService { }

使用 MEF 目录,您可以注册该类型。Autofac 将找到导出的接口并提供服务。

var catalog = new TypeCatalog(typeof(Component));
builder.RegisterComposablePartCatalog(catalog);
var container = builder.Build();

// 解决得到的 IService 实现将由类型 Component 提供。
var obj = container.Resolve<IService>();

将 Autofac 组件提供给 MEF 扩展

Autofac 组件不会自动提供给 MEF 扩展导入。也就是说,如果您使用 Autofac 解决一个使用 MEF 注册的组件,只允许使用 MEF 注册的其他服务来满足其依赖关系。

要将 Autofac 组件提供给 MEF,请使用 Exported() 扩展方法:

builder.RegisterType<Component>()
       .Exported(x => x.As<IService>().WithMetadata("SomeData", 42));

再次强调,这是一次性操作。它允许 Autofac 为在 Autofac 中注册的 MEF 组件提供依赖项 - 它不会将 Autofac 注册项导出到 MEF 目录中以供解决。

使用元数据

Autofac MEF 集成为现有的 Lazy<T> 支持添加了 Lazy<T, TMetadata> 关系支持。

例如,假设您有一个定义元数据的接口:

public interface IAgeMetadata
{
    int Age { get; }
}

您可以注册 Autofac 服务并使用 Lazy<T, TMetadata> 关系,方法是添加 MEF 元数据注册源:

var builder = new ContainerBuilder();

// 这会添加 MEF 关系注册源。
builder.RegisterMetadataRegistrationSources();

builder.RegisterType<Component>()
       .WithMetadata<IAgeMetadata>(m => m.For(value => value.Age, 42));
var container = builder.Build();

然后,您可以从此处解决 Lazy<T, TMetadata>

using (var scope = container.BeginLifetimeScope())
{
    var lazy = scope.Resolve<Lazy<Component, IAgeMetadata>>();

    // lazy.Metadata.Age == 42
}

已知问题:如果您在 MEF 的 [Imports] 上有一个 Lazy<T, TMetadata> 值,此时对象 T 不会延迟实例化在 Autofac.Mef 仓库中已为此问题提交了一个问题。 如果您想帮忙,我们很乐意接受一个 PR!

已知问题/陷阱

  • Autofac 和 MEF 的集成是单向的。 它不允许 MEF 组合容器访问在 Autofac 中注册的东西。相反,它基本上采用 MEF 注册语义,并帮助填充一个 Autofac 容器。之后,您期望从 Autofac 解决东西,而不是从 MEF 容器。
  • 懒加载元数据导入不工作。 如果您有一个 MEF 的 [Imports] 在一个 Lazy<T, TMetadata> 值上,此时对象 T 不会延迟实例化在 Autofac.Mef 仓库中已为此问题提交了一个问题。
  • 不支持开放泛型导出。 如果您在一个 MEF 组件上有一个像 [Export(typeof(A<>))] 这样的属性,Autofac 将无法正确处理这个导出,解决此类类型的对象将失败。在 Autofac.Mef 仓库中已为此问题提交了一个问题。
在本文档中