2012-04-29 9 views
14

Estoy trabajando en una aplicación WPF de tamaño medio (MVVM) que debería ser extensible y fácil de mantener en el futuro. Por lo tanto, decidí usar un contenedor IoC (Unity en este caso) para mantener las cosas flexibles.¿Dónde colocar y configurar el contenedor IoC en una aplicación WPF?

Sin embargo, no estoy seguro de dónde colocar y configurar Unity en una aplicación WPF.

Supongo que el contenedor debe ser accesible globalmente, por lo que probablemente debería ir a la clase de Aplicación. ¿Pero debería hacerlo como propiedad estática? ¿Debo configurarlo en el controlador de eventos Application_Startup()?

Ej:

/// <summary> 
/// Interaction logic for App.xaml 
/// </summary> 
public partial class App : Application 
{ 
    public static UnityContainer MyUnityContainer; 


    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     // instantiate and configure Unity 
    } 
} 

De esta manera voy a ser capaz de acceder contenedor desde cualquier lugar de la aplicación a través de la propiedad estática:

App.MyUnityContainer 

supongo que esto es una manera de hacerlo, pero lo No estoy seguro de si hay mejores prácticas para este problema, específicamente para las aplicaciones de WPF.

Respuesta

8

Eche un vistazo a Composition Root Pattern. Lo que quiere hacer es inicializarlo en su controlador de eventos de inicio y olvidarse de su existencia para el resto de la aplicación.

Está tratando de implementar el Service Locator Pattern, que según muchos is an inferior solution a este problema.

+0

¿Cómo puedo olvidar por completo su existencia? Querrá resolver las dependencias en el nivel superior de su gráfico de dependencia, ¿no? Quiero decir, por ejemplo, se supone que un controlador de evento de clic de botón debe guardar 'Cliente' en la base de datos, que usa' CustomerRepository'. ¿No tendrá que resolver 'CustomerRepository' para usarlo, por lo tanto, necesitará el contenedor IoC nuevamente? –

+1

@JoaoMilasch ¿Nivel superior? Absolutamente. ¿Pero por qué el nivel superior sería una ventana y no la clase de la aplicación? En su caso, tiene una Ventana que requiere un repositorio, que se puede inyectar a través de la Inyección de Constructor. A continuación, puede resolver MainWindow en el evento de inicio de su aplicación llamando al contenedor. –

+0

Aha!Usted respondió mi pregunta indirectamente y todo tiene sentido ahora. Estaba pensando que necesitaba configurar el contenedor en la clase de la aplicación, pero Windows necesitaría acceso directo al contenedor configurado. En cambio, si hago lo que sugiere, el objeto contenedor solo deberá existir en la clase de la aplicación. ¡Corrígeme si me equivoco, por favor! :) ¡Gracias! –

5

Déjeme publicar lo que he concluido y espero que ayude a la gente. ¡Corrija si hay algo mal! : P

supongo que estaríamos buscando en algo como esto:

/// <summary> 
/// Interaction logic for App.xaml 
/// </summary> 
public partial class App : Application 
{ 
    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     UnityContainer myUnityContainer = new UnityContainer(); 
     //make sure your container is configured 
     myUnityContainer.RegisterType<ISomeDependency, SomeDependencyImplementation>(); 
     myUnityContainer.RegisterType<IMainWindow, MainWindow>(); 

     myUnityContainer.Resolve<IMainWindow>().Show(); 
    } 
} 

public partial class MainWindow : Window, IMainWindow 
{ 
    private ISomeDependency _someDependency; 

    public MainWindow(ISomeDependency someDependency) 
    { 
     _someDependency = someDependency; 
    } 
} 

cuenta que no hay variables globales o únicos, el contenedor sobrevive tanto tiempo como lo hace MainWindow y todas las dependencias detrás de este punto de entrada más en el gráfico de composición se resuelven automágicamente siempre que el contenedor los conozca.

+1

Creo que quiere RegisterType en lugar de Register. –

+0

Gracias por la corrección @JacobBrewer –

+1

@JoaoMilasch falta una parte y (no está claro para mí) cómo se "promociona" el contenedor en uno principal, algo similar a lo que puedes tener en asp.net MVC por "GlobalConfiguration.Configuration" .DependencyResolver ". La opción "Resolver" solo verifica si todas las dependencias en el contenedor tienen una referencia. – stenly

1

Según la nueva versión del contenedor Unity, también debemos registrar su propia instancia para obtenerlo en modelos de visualización mediante la inyección del constructor. archivo

App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) 
{ 
     var unityIoC = new UnityContainer(); 
     unityIoC.RegisterTypes(AllClasses.FromAssembliesInBasePath(), WithMappings.FromMatchingInterface, WithName.Default); 
     unityIoC.RegisterInstance(typeof(IUnityContainer), unityIoC); 
} 

clase View Modelo

[InjectionConstructor] 
public MyViewModel(IUnityContainer container) 
{ 
} 

Ahora estaría disponible para nosotros en vista del modelo de contenedores unidad y se puede utilizar para resolver.

Cuestiones relacionadas