Este es un escenario de patrón de decorador bastante sencillo, con la complicación de que el tipo decorado tiene un parámetro constructor que depende del tipo en que se está inyectando.Configurar Unity para resolver un tipo que toma una dependencia decorada que tiene un parámetro que varía con el tipo en el que se inyecta
que tienen una interfaz de esta manera:
interface IThing
{
void Do();
}
Y una implementación de esta manera:
class RealThing : IThing
{
public RealThing(string configuration)
{
... implementation ...
}
public void Do()
{
... implementation ...
}
}
Y un decorador de la siguiente manera:
class DecoratingThing : IThing
{
IThing _innerThing;
public DecoratingThing(IThing thing)
{
_innerThing = thing;
}
public void Do()
{
_innerThing.Do();
}
}
Por último, tengo algunos tipos que requieren un IThing
, llamado Depender1
, Depender2
etc.
class DependerX()
{
public DependerX(IThing thing)
{
... implementation ...
}
}
Quiero configurar un contenedor COI para resolver los casos de DependerX
de tal manera que se inyectan con RealThing
decorado con una DecoratingThing
. Importante: Cada DependerX
tipo requiere un valor diferente de configuration
que se pasa al constructor de su RealThing
, diga "ConfigX" en cada caso. p.ej. El trabajo realizado por el contenedor IoC podría ser:
new Depender1(new DecoratingThing(new RealThing("Config1")));
new Depender2(new DecoratingThing(new RealThing("Config2")));
... y así sucesivamente.
en la unidad, esto parece bastante torpe para configurar ya que tengo que mezclar en el decorador con el decorado:
container.RegisterType<IThing, DecoratingThing>("ConfigX",
new InjectionFactory(container => new DecoratingThing(new RealThing("ConfigX"));
container.RegisterType<DependerX>(
new InjectionConstructor(new ResolvedParameter<IThing>("ConfigX");
y repetir, que viola SECO muy bien, para cada DependerX
.
Lo que me gustaría hacer es eliminar la necesidad de integrar la construcción de RealThing
en la construcción de DecoratingThing
en cada registro con nombre de IThing
- y declarar la decoración de una sola vez. Esto es así, por ejemplo, que si la decoración necesita cambiar en el futuro, es más fácil volver a configurarla. Lo mejor que se me ocurrió es este método de ayuda para la inscripción:
void RegisterDepender<TDepender>(IUnityContainer container, string config)
{
container.RegisterType<TDepender>(new InjectionConstructor(
new ResolvedParameter<IThing>(config)));
container.RegisterType<IThing, DecoratingThing>(config,
new InjectionFactory(c => new DecoratingThing(new RealThing(config))));
}
Esto elimina la repetición, al menos, pero todavía tienen que integrar la construcción de la RealThing
dentro del DecoratingThing
- esto significa que no puedo variar su vida independientemente por ejemplo. No puedo registrar IThing
nuevamente para hacer esto porque he usado mi registro de esa interfaz para el nombre. Si yo quiero hacer eso tengo que introducir otro conjunto de instancias con nombre, así:
void RegisterDepender<TDepender>(IUnityContainer container, string config)
{
string realConfig = "Real" + config;
container.RegisterType<TDepender>(new InjectionConstructor(
new ResolvedParameter<IThing>(config)));
container.RegisterType<IThing, DecoratingThing>(config,
new InjectionFactory(c => new DecoratingThing(
container.Resolve<IThing>(realConfig))));
container.RegisterType<IThing, RealThing>(realConfig,
new ContainerControlledLifetimeManager(),
new InjectionConstructor(config));
}
¿Es esta realmente la mejor opción? Se siente complejo y potencialmente difícil para los que vendrán después de grok. ¿Tienen otros contenedores IoC una forma convincente de cubrir este escenario? Dado que el patrón de cómo funciona la inyección se repite para cada DependerX, ¿hay alguna forma de usar solo una instancia con nombre en el nivel superior (DependerX
)?
¿Algún otro comentario?
Gracias Mark. Creo que un enfoque basado en convenciones es el camino a seguir en mi escenario particular. Eso no quiere decir que otros enfoques (como la idea de interceptación anterior) no sean igualmente válidos. ¡Es bueno saber que no estoy fuera de los caminos trillados aquí! –