Autofac 可以组合具有 Mef 依赖项的现有对象吗?

Can Autofac compose existing objects with Mef dependencies?

我正在将基于 mef 的 ServiceLocator 与 Autofac 集成。当前定位器能够通过设置 CompositionBatch 然后在对象上注入依赖项来组合 existing 对象。一个简单的复制:

public void MefCompositionContainer_CanComposeExistingObjects()
{
    //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. Mef is able to compose existing object
    var objectWithPropertyImport = new ClassWithPropertyImport();
    Compose(container, objectWithPropertyImport);
    objectWithPropertyImport.ImportOfMefExport.Should().NotBeNull();
}

static T Compose<T>(CompositionContainer container, T value)
{
    var batch = new CompositionBatch();
    batch.AddPart(value);
    container.Compose(batch);
    return value;
}

以下 类 是必需的:

[Export]
public class MefExport { }

//Note that this class does not have the [Export] attribute
public class ClassWithPropertyImport
{
    [Import]
    public MefExport ImportOfMefExport { get; set; }
}

是否可以用 Autofac 完成同样的事情?如果是这样 - 应该在此处添加/更改什么以组成 objectWithPropertyImport?

public void Autofac_CanComposeExistingObjects()
{
    //1. Initialize Mef
    var composablePartCatalogs = new List<ComposablePartCatalog>
    {
        new AssemblyCatalog(Assembly.GetExecutingAssembly())
        //A lot more here..
    };

    var aggregateCatalog = new AggregateCatalog(composablePartCatalogs);

    //2. Initialize Autofac and setup mef-integration
    var builder = new ContainerBuilder();
    builder.Register(c => new AutofacExport()).Exported(x => x.As<AutofacExport>());
    builder.RegisterComposablePartCatalog(aggregateCatalog);

    var ioc = builder.Build();

    var objectWithPropertyImport = new ClassWithPropertyImport();
    // Now what?

    // Updated according to solution from Travis Illig.
    // The following code works for me:
    ioc.InjectProperties(objectWithPropertyImport);
    objectWithPropertyImport.ImportOfMefExport.Should().NotBeNull();
}

如果您需要做的只是使用 Autofac 注入新对象的属性,则在生命周期范围/容器上使用 InjectProperties 方法。

using Autofac;

public class ClassWithPropertyImport
{
    public MyExport ImportedProperty { get; set; }
}

public class MyExport { }

var builder = new ContainerBuilder();
builder.RegisterType<MyExport>();
var container = builder.Build();

using(var scope = container.BeginLifetimeScope())
{
    var c = new ClassWithPropertyImport();
    scope.InjectProperties(c);
    c.ImportedProperty.Should().NotBeNull();
}

只要您注入的类型已在 Autofac 中注册,它就应该可以正常工作。您不需要注册要注入的东西的类型。 (请注意 ClassWithPropertyImport 未在 Autofac 中注册,但 MyExport class 已注册。)

请记住,这确实意味着 Autofac 需要解析 MyExport 类型 - 因此如果它具有依赖项,则也需要向 Autofac 注册这些依赖项。