自定义'ExportFactory'

Xaq*_*ron 6 c# factory mef export

使用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);
Run Code Online (Sandbox Code Playgroud)

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

可在此处找到示例项目(带无参数构造函数).

Wim*_*nen 5

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

你的错误是你想到这个魔术还可以自动为你自己的替代工作,ExportFactory你叫SrviceProviderFactory.这不是真的.当您导入SrviceProviderFactory<IFoo,IFooMetadata>某处时,MEF会逐字寻找该类型的导出.

直截了当的解决方案是给它这个输出.为每个IServiceProvider实现手动导出工厂.例如,如果您有FooServiceProvider:

public class FooServiceProvider : IServiceProvider
{
    public FooServiceProvider(Dependency dependency)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你还需要一个FooServiceProviderFactory:

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

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

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);
       ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这里令人讨厌的是,对于每个服务提供者实现,您还需要创建和导出工厂实现.您可以通过创建公共工厂基类(如您的SrviceProviderFactory)来节省工作,但仍然必须派生特定的类,因为您不能在MEF导出中使用泛型类型参数.更新:我相信.NET 4.5现在支持导出开放泛型类型.

这就是为什么我已经建议您导出Func代替,但显然你不喜欢这个问题的答案.

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