自定义'ExportFactory'

时间:2010-12-11 15:37:10

标签: c# export mef factory

使用MEF的桌面应用程序会导入许多“ServiceProviders”。每个部分(ServiceProvider)都是一个单独的DLL内的类。 所有DLL都在“插件”文件夹中,供桌面应用程序使用。

由于我需要新部件的实例,ExportFactory是最佳选择。问题是我的部件有构造函数。我需要将一些参数传递给ExportFactory不支持的部件的构造函数(MEF2,Preview2)。

我需要这样的东西:

// Each part has its own dependency
Dependency dependency = LoadDependency(myPart.Metedata["Name"]);
// Injecting dependency into part's constructor
myPart.CreateExport(dependency);

我不想从我的零件方面导入任何东西。

可以找到示例项目(带无参数构造函数)here

1 个答案:

答案 0 :(得分:5)

当MEF看到类型ExportFactory<IFoo>的导入时,它会以特殊方式对待它。它不是按字面意思查找ExportFactory<IFoo>导出,而是查找IFoo导出,并神奇地为该类型生成工厂。

您的错误在于,您希望此魔法自动适用于您自己替换为ExportFactory的{​​{1}}。这不是真的。当您在某处导入SrviceProviderFactory时,MEF会逐字地查找该类型的导出。

直接的解决方案是给它这个导出。为每个IServiceProvider实现手动导出工厂。例如,如果您有SrviceProviderFactory<IFoo,IFooMetadata>

FooServiceProvider

然后你还需要一个FooServiceProviderFactory:

public class FooServiceProvider : IServiceProvider
{
    public FooServiceProvider(Dependency dependency)
    {
        ...
    }
}

然后您的导入器可以根据元数据选择合适的工厂:

[Export(typeof(IServiceProviderFactory))]
[ExportMetaData("foo", "bar")]
public class FooServiceProviderFactory : IServiceProviderFactory
{
    public IServiceProvider CreateServiceProvider(Dependency d)
    {
       return new FooServiceProvider(d);
    }
}

这里令人讨厌的是,对于每个服务提供者实现,您还需要创建和导出工厂实现。您可以通过创建公共工厂基类(如public class FactoryUser { [ImportMany] public Lazy<IServiceProviderFactory,IDictionary<string,object>>[] Factories { get; set; } public void DoSomething() { var factory = Factories.First(x => x.Metadata["foo"] == "bar").Value; var serviceProvider = factory.CreateServiceProvider(someDependency); ... } } )来节省工作,但仍然必须派生特定的类,因为您不能在MEF导出中使用泛型类型参数。 更新:我相信.NET 4.5现在支持导出开放泛型类型。

这就是I already suggested you export Func instead的原因,但显然你不喜欢这个答案。

你也可以尝试复制SrviceProviderFactory魔法。这是可能的,但是MEF的一个非常先进的用例。如果你想这样做,我建议你看一下ExportFactory的MEF来源,看看如何构建你自己的实现并支持参数。