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.
精彩评论