2012-05-30 10 views
6

En mi aplicación Prism, el contenedor MEF está disponible desde dentro de la clase Bootstrapper a través de la propiedad Contenedor.¿Por qué el contenedor MEF no está disponible en los módulos?

Pero no es dentro del módulo de clase (IModule). Solo puedo importar el contenedor a través de IServiceLocator.

¿Por qué? Pensé que tenía sentido usar una interfaz común contra la tecnología concreta, pero la guía de Prism 4.1 nos pide que no usemos IServiceLocator (en Considerations for Using IServiceLocator).

Respuesta

6

Creo que no corresponde a Prism o MEF, sino al principio de Dependency Injection y las mejores prácticas en general. (Sí, anudé que MEF no es contenedor DI, pero aquí se usa casi como contenedor DI, así que supongo que usaré las mismas prácticas aquí).

En las mejores prácticas de DI (this libro es muy bueno, lo recomiendo) que es bueno tener este tipo de pasos de "flujo de trabajo" DI:

  • registro de todos los tipos necesarios (en Prisma - por programa previo. (método))
  • objeto raíz determinación ConfigureCatalog (con todos los objetos anidados En Prisma -. por Bootstrapper.CreateShell() método)
  • utilizar su objeto raíz
  • versión que objeto raíz

Idealmente, NO deberías usar el contenedor DI nunca más. Su código NO debe saber sobre la existencia del contenedor DI (de este lado, Unity es realmente un contenedor DI, porque puede escribir un código que no sabrá sobre el uso del contenedor DI). Si tu código lo sabe, DEPENDE de un contenedor DI, y es malo.

PS.Si desea utilizar contenedores MEF en su módulo de todos modos (por ejemplo, porque no está muy familiarizado con el paradigma DI o si tiene algunas tareas muy específicas), se puede intentar algo como:

[ModuleExport(typeof(YourModule))] 
public class YourModule : IModule 
{ 
    public static CompositionContainer CompositionContainer; 

    [ImportingConstructor] 
    public void YourModule(CompositionContainer container) 
    { 
     this.CompositionContainer = container; 
    } 
} 

no hacer olvide registrar su contenedor MEF en su Boostrapper:

public class YourBootstrapper: MefBootstrapper 
{ 
    protected override CompositionContainer CreateContainer() 
    { 
     var container = base.CreateContainer(); 
     container.ComposeExportedValue(container); 
     return container; 
    } 
} 
+1

Aunque estoy de acuerdo con las mejores prácticas, la documentación del prisma establece claramente que también puede utilizar el método Initialize de su método para "Registrar servicios compartidos con el contenedor de inyección de dependencias de la aplicación". http://msdn.microsoft.com/en-us/library/gg405479%28v=pandp.40%29.aspx – Console

+2

Si no se supone que debemos saber sobre el contenedor, ¿cómo pueden los módulos registrar nuevos servicios compartidos? – Benjamin

+0

El 'ComposeExportedValue' mencionado es un método de extensión en' System.ComponentModel.Composition.AttributedModelServices' – jan

0

Tenga en cuenta que estoy usando una versión anterior de Prism y que la estoy usando con UnityContainer, pero deben aplicarse los mismos principios.

Defina su clase de módulo para tomar un contenedor en el constructor.

Aquí hay un ejemplo usando la Unidad:

public class Module : IModule 
{ 
    public static IUnityContainer Container; 

    public Module(IUnityContainer container) 
    { 
     Container = container; 
    } 
} 

Si se define un constructor que toma un contenedor, que será llamado por el método ApplicationBootstrapper.Run().

Probé con un constructor predeterminado sin parámetros y un constructor de sobrecarga que toma el contenedor y se llamó al segundo constructor.

También comprobé que solo tenía el constructor predeterminado y se llamó. Sugeriría que cambies tu constructor para agregar un parámetro tomando un contenedor.

Tener un contenedor en su clase de módulo le permitirá registrar tipos en su método Initialize.

En cuanto a ServiceLocator, ese es un patrón ligeramente diferente que yo recomendaría usar en casos donde no pueda obtener sus dependencias creadas por el contenedor por alguna razón.

+0

Estaba tratando de hacer eso. MEF utiliza el tipo CompositionContainer en lugar de IUnityContainer de Unity. Pero mi constructor con parámetro escribió CompositionContainer no ejecutándose. –

+0

@reito: ¿También tiene un constructor predeterminado y cómo llama al método de ejecución ApplicationBootstrapper? – Gilles

+0

Ya no tengo constructores, solo este. El método Bootstrapper Run realiza una llamada dentro del método OnStartup de mi clase de aplicación. –

Cuestiones relacionadas