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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With