Estoy trabajando en una aplicación WPF que utiliza una arquitectura MVC y un contenedor IOC. Actualmente, estoy luchando con un problema de diseño que involucra el alcance y el tiempo de vida de ciertos componentes proporcionados por el contenedor. Aquí está la situación.Cómo implementar un ciclo de vida por visión para componentes inyectados IoC
Voy a generalizar diciendo algo incorrectamente que los contenedores IOC admiten ciclos de vida de dos componentes, singleton y transitorio. Pero lo que necesitamos es un término medio para ciertos conjuntos de componentes.
Considere una vista que muestra una lista de registros en una grilla. Cuando el usuario hace clic en un registro, se abre una nueva vista para mostrar los detalles del registro y permitir la edición. El usuario puede tener muchas de esas vistas abiertas, cada una mostrando un registro diferente. Cada vista tiene su propio modelo y controlador también.
En el contexto de un conjunto de modelo-vista-controlador determinado, hay algunos componentes, como los cuadros de diálogo que se inyectan de forma transitoria y de forma diferida. Es decir que queremos una nueva instancia cada vez que necesitamos mostrar una y dado que la mayoría de estos transitorios solo son necesarios si el usuario realiza alguna acción, inicialmente solo inyectamos un delegado de fábrica. El delegado luego se invoca según sea necesario para llevar a cabo la resolución de dependencia real.
Más allá del modelo, la vista y el controlador, hay una gran cantidad de otros componentes para los que queremos una instancia por conjunto m-v-c. Por ejemplo, estamos implementando el patrón de conversación de NHibernate que requiere que se abra una sesión cuando la vista se abre y permanece abierta hasta que se cierra. Del mismo modo, cada conjunto necesita su propio corredor de eventos compartidos y, potencialmente, algunas "otras cosas". Si todas estas dependencias se resolvieran en el momento en que se creó la vista, esto no sería un problema. Podríamos declararlos todos como transitorios y terminar con ellos.
Sin embargo, algunas de esas dependencias resueltamente laxas tienen dependencias en el modelo, el controlador o las "otras cosas". Entonces, el problema es que, al resolver una dependencia diferida, el contenedor detrás del delegado necesita inyectar la instancia correcta de cada dependencia. Esto, por supuesto, implica que el delegado mismo está de alguna manera vinculado al conjunto m-v-c, pero eso no debería ser un problema si el problema más grande se puede resolver.
Ahora, arriba, dije que estaba simplificando demasiado la lista de ciclos de vida admitidos. La mayoría de los contenedores admiten algunos ciclos de vida intermedios, por ejemplo, por subproceso o solicitud previa, que permiten un alcance que es conceptualmente similar a lo que estamos buscando. Sin embargo, esto no se aplica en un escenario de IU interactivo. No es el caso que cada vista esté en su propio hilo o en algún otro contexto conveniente que proporcione la base para el alcance.
Por lo tanto, mi pregunta es, ¿cuál es la mejor manera de implementar un ciclo de vida de componente por vista (o por cualquier contexto arbitrario) utilizando un contenedor IOC. Nuestro contenedor actual es Unity, pero nos hemos abstraído lo suficiente como para poder cambiar sin demasiada dificultad. Entonces, si esto se implementa más fácilmente en otro contenedor o se implementa de la caja, podríamos considerar cambiarlo.
Consideré esta posibilidad, sin embargo, no tengo clara la relación entre los contenedores para niños y los ciclos de vida de los componentes. Específicamente parece que diferentes contenedores se comportan de manera diferente con respecto a esto. El contenedor Castle usa las mismas instancias singleton en todos los contenedores en la misma jerarquía. El ContainerControlledLifetimeManager de Unity, en su nombre, implica lo contrario, que cada contenedor hijo obtenga un conjunto nuevo completo de todos los componentes controlados por contenedor. Es necesario que haya otro administrador de por vida que esté en el medio ... –
¡Hah! Eso me hizo pensar en una nueva consulta de Google para probar y acabo de encontrar el HierarchicalLifetimeManager (http://msdn.microsoft.com/en-us/library/ff660872(PandP.20).aspx). Esto se ve como lo que necesito. ¡Gracias! –
@Kenneth: Estoy de acuerdo con Bryan. El truco consiste en inyectar un IUnitOfWorkFactory (o delegar si lo desea) en el controlador y dejar que ese controlador (o quienquiera que controle la duración de la sesión) cree una unidad de trabajo utilizando esa fábrica. Busque por ejemplo en este artículo: http://bit.ly/bF7jL3. – Steven