2010-12-11 28 views
6

Una aplicación de escritorio que usa MEF importa muchos 'ServiceProviders'. Cada parte (ServiceProvider) es una clase dentro de una DLL separada. Todos los archivos DLL están en carpeta 'Plug-in" que es utilizado por la aplicación de escritorio.Custom 'ExportFactory'

Ya que necesitaba nuevas instancias de mis partes, ExportFactory era la mejor opción. El problema es que mis partes tener constructores. Tengo que pasar algunos parámetros en el constructor . de la parte que no está soportada por ExportFactory (MEF2, preview2)

necesito algo como esto:.

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

no quiero importar nada de mi partes del lado

Se puede encontrar un proyecto de ejemplo (con constructor sin parámetros) here.

+0

Estoy confundido. Usted habla de 'MyExportFactory' pero luego muestra una clase llamada' SrviceProviderFactory'. También define un método 'CreateServiceProvider' pero luego en otro lugar lo llama' CreateMyExport'. ¿Cambió el nombre de las cosas al escribir la pregunta? –

Respuesta

5

Cuando MEF ve una importación del tipo ExportFactory<IFoo>, trata esto de una manera especial. En lugar de buscar literalmente una exportación ExportFactory<IFoo>, busca una exportación IFoo y mágicamente genera una fábrica para ese tipo.

Tu error es que esperas que esta magia también funcione automáticamente para tu propia alternativa al ExportFactory al que llamaste SrviceProviderFactory. Esto no es verdad. Cuando importa SrviceProviderFactory<IFoo,IFooMetadata> en alguna parte, MEF literalmente busca una exportación de ese tipo.

La solución directa es darle esta exportación. Exporte manualmente una fábrica para cada implementación IServiceProvider. Por ejemplo, si tiene un FooServiceProvider:

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

A continuación, también necesita tener un FooServiceProviderFactory:

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

Y entonces su importador puede seleccionar la fábrica de derecho basado en metadatos:

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

Lo molesto aquí es que para cada implementación de proveedor de servicio, también necesita crear y exportar una implementación de fábrica. Puede guardar el trabajo creando una clase base de fábrica común (como su SrviceProviderFactory), pero aún debe derivar clases específicas porque no puede usar parámetros genéricos de tipo en las exportaciones de MEF. update: Creo que .NET 4.5 ahora es compatible con la exportación de tipos genéricos abiertos.

Por eso I already suggested you export Func instead, pero al parecer que no le gustó esa respuesta.

También puede tratar de replicar la magia ExportFactory. Esto es posible, pero un caso de uso muy avanzado de MEF. Si quieres hacerlo, te sugiero que eches un vistazo a las fuentes MEF de ExportFactoryProvider para ver cómo crear tu propia implementación con soporte para parámetros.