开发者

Custom 'ExportFactory'

A desktop application using MEF imports many 'ServiceProviders'. Each part (ServiceProvider) is a class inside a separate DLL. All DLLs are in 'Plugin" folder which is used by desktop application.

Since I needed new Instances of my parts, ExportFactory was the best choice. The problem is my parts have constructors. I need pass some parameters into constructor of the part which is not supported by ExportFactory (MEF2, Preview2).

I need something like this:

// Each part has its own dependency
Dependency dependency = LoadDependency(myPart.Metedata["Name"]);
// Injecting dependency into part's constructor
myPart.CreateExport(dependency);
开发者_StackOverflow中文版

I don't want import anything from my parts-side.

A sample project (with parameter-less constructor) can be found here.


When MEF sees an import of the type ExportFactory<IFoo>, it treats this in a special way. Instead of looking literally for an ExportFactory<IFoo> export, it looks instead for a IFoo export and magically generates a factory for that type.

Your mistake is that you expect this magic to also automatically work for your own alternative to ExportFactory which you called SrviceProviderFactory. This is not true. When you import SrviceProviderFactory<IFoo,IFooMetadata> somewhere, MEF literally looks for an export of that type.

The straightforward solution is to give it this export. Manually export a factory for each IServiceProvider implementation. For example, if you have a FooServiceProvider:

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

Then you also need to have a FooServiceProviderFactory:

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

And then your importer can select the right factory based on metadata:

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);
       ...
    }
}

The annoying thing here is that for each service provider implementation, you also need to create and export a factory implementation. You can save work by creating a common factory base class (like your SrviceProviderFactory) but you still have to derive specific classes because you can't use generic type parameters in MEF exports. update: I believe .NET 4.5 now supports exporting open generic types.

That's why I already suggested you export Func instead, but apparently you didn't like that answer.

You could also try to replicate the ExportFactory magic. This is possible but a very advanced use case of MEF. If you want to do that I suggest you take a look at the MEF sources of ExportFactoryProvider to see how to build your own implementation with support for parameters.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜