Questo è uno scenario di pattern decoratore abbastanza semplice, con la complicazione che il tipo decorato ha un parametro costruttore che dipende dal tipo in cui viene iniettato.Configurazione di Unity per risolvere un tipo che accetta una dipendenza decorata con un parametro che varia con il tipo in cui viene iniettata
devo un'interfaccia simile a questo:
interface IThing
{
void Do();
}
E un'implementazione del genere:
class RealThing : IThing
{
public RealThing(string configuration)
{
... implementation ...
}
public void Do()
{
... implementation ...
}
}
e un decoratore come questo:
class DecoratingThing : IThing
{
IThing _innerThing;
public DecoratingThing(IThing thing)
{
_innerThing = thing;
}
public void Do()
{
_innerThing.Do();
}
}
Infine, ho alcuni tipi che richiedono un IThing
, chiamato Depender1
, Depender2
ecc.
class DependerX()
{
public DependerX(IThing thing)
{
... implementation ...
}
}
Voglio configurare un contenitore CIO per risolvere i casi di DependerX
tale che essi vengono iniettati con RealThing
decorato con un DecoratingThing
. Importante: Ogni DependerX
tipo richiede un diverso valore di configuration
da passare al costruttore del suo RealThing
, ad esempio "ConfigX" in ogni caso. per esempio. Il lavoro svolto dal contenitore CIO potrebbe essere:
new Depender1(new DecoratingThing(new RealThing("Config1")));
new Depender2(new DecoratingThing(new RealThing("Config2")));
... e così via.
In Unity, questo sembra abbastanza goffo configurare come devo mescolare il decoratore con la decorato:
container.RegisterType<IThing, DecoratingThing>("ConfigX",
new InjectionFactory(container => new DecoratingThing(new RealThing("ConfigX"));
container.RegisterType<DependerX>(
new InjectionConstructor(new ResolvedParameter<IThing>("ConfigX");
E ripetere, violando DRY bene, per ogni DependerX
.
Quello che mi piacerebbe fare è rimuovere la necessità di incorporare la costruzione del RealThing
nella costruzione di DecoratingThing
in ogni registrazione denominata di IThing
- e dichiarare la decorazione solo una volta. È così, per esempio, che se la decorazione deve cambiare in futuro, è più facile riconfigurare. Il migliore mi è venuto in mente è questo metodo di supporto per la registrazione:
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))));
}
Ciò elimina la ripetizione almeno, ma ho ancora incorporare la costruzione del RealThing
all'interno del DecoratingThing
- questo significa che non posso variare la loro vita indipendentemente per esempio. Non riesco a registrare di nuovo IThing
perché ho esaurito la mia registrazione di quell'interfaccia per il nome. Se voglio fare che devo introdurre un altro insieme di istanze denominate in questo modo:
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));
}
È questo davvero l'opzione migliore? Sembra complesso e potenzialmente difficile per quelli che verranno dopo averli divorati. Gli altri contenitori IoC hanno un modo convincente per coprire questo scenario? Poiché il pattern per il funzionamento dell'iniezione viene ripetuto per ciascun DependerX, esiste un modo per utilizzare solo un'istanza denominata in alto (DependerX
)?
Altri commenti?
Grazie Marco. Penso che un approccio basato sulla convenzione sia la strada da percorrere nel mio particolare scenario. Ciò non significa che altri approcci (come l'idea di intercettazione di cui sopra) non siano ugualmente validi. È bello sapere che non sono molto lontano da qui! –