Jag finner ofta behov av att låta alla objekt av en och samma klass ha tillgång till samma service. Det känns då som slöseri av både tid och minne att skicka in servicen till varje enskilt objekt. I stället vill jag skicka in det till hela klassen och låta det ligga på klassnivå. Det låter som att du tänker på två problem samtidigt? Hur når Order-objekt ioc? Injectas ioc i objekten (alt. klassen) eller är det en global variabel? En annan sak... I din exempelkod, >Hur når Order-objekt ioc? Injectas ioc i objekten (alt. klassen) eller är det en global variabel?DI på klassnivå
Exempel:
Man har en webbutik med order- och kundobjekt.
Ett orderobjekt kan via en kundrepository returnera kunden som har lagt ordern.
Om man hämtar ut en följd av ordrar, t.ex. för att visa en lista över ordrar och kunderna som har lagt dem, behöver varje order ha tillgång till kundrepositoryn. Detta samtidigt som ordrarna skall fyllas i med information från databasen.
Jag har aldrig sett någon diskussion om DI på klassnivå. Är det inget som görs? I så fall, hur gör man i stället?Sv: DI på klassnivå
Dels att det "känns konstigt" att skicka med kundrepo till varje order, när ordrarna skapas?
Dels att det skulle vara prestandaproblem?
Vad man brukar göra är ju IoC-containers, typ något i stil med:
order.GetCustomer(){
return ioc.GetObjectForType<ICustomerRepo>().GetCustomerByID(this.CustomerID);
}
Vilket då skulle lösa första frågan.
(ioc är i praktiken en dictionary från "interface" till object.)
Jag gillar det inte, känns som singletons. Av samma anledning gillar jag inte statiska klasser, känns som singletons.
En annan variant som jag föredrar när det rör sig om "rapporter" är att skita i det och binda ihop objekten med referenser direkt - hämta alltihop som är relevant.
Håller dock med om att det känns lite vagt. Rekommendationerna slutar ganska exakt där det blir verkligt och sen blir det "det beror på".
Har du ett lite mer konkret exempel?Sv:DI på klassnivå
Ett litet mer konkret exempel? Jag som tyckte att mitt exempel var ganska konkret... :-oSv:DI på klassnivå
<code>
order.GetCustomer(){
return ioc.GetObjectForType<ICustomerRepo>().GetCustomerByID(this.CustomerID);
}
</code>
blir det inte jobbigt om ett orderobjekt skall ha en annan ICustomerRepo än den vanliga? Förlorar man inte en del av idén med dependency injection?Sv: DI på klassnivå
Se listan på http://en.wikipedia.org/wiki/Inversion_of_control
Vanligaste jag har sett är service locator, som i sin tur oftast är något slags globalt objekt. Hemskt obehagligt enligt mig. (Ofta kan man välja mellan olika sorter i ett lib, och att dessutom kunna injecta är relativt vanligt.)
Tycker hela konceptet är överabstraherat, det underliggande problemet är inte så komplicerat.
>blir det inte jobbigt om ett orderobjekt skall ha en annan ICustomerRepo än den vanliga? Förlorar man inte en del av idén med dependency injection?
Yes, i allra högsta grad. Därför jag hatar det.
Brukar väl finnas något sätt att speca vilken "specialvariant" man vill använda också, visserligen.
Fast samma brist får du ju om du skulle ha en klass-DI, inte sant?
--
Sen skulle jag inte säga att det i sig är en speciellt viktig del. Jag förespråkar framförallt isolering av delar från varandra, som viktigaste effekten av vettigt användande av DI.
Dependency Injection är ju egentligen inget annat än den vanligaste användningen av interfaces (som i sin tur är den vanligaste användningen av arv i C++-familjen).
Alltså; kan man låta all kommunikation mellan arkitekturellt logiska delar ske via små gemensamma interfaces så har man förhoppningsvis en ganska tydlig struktur. Kan man utkristallisera kontentan av en enhet i ett litet interface så är den förmodligen hyfsat genomtänkt, utbytbarheten är trevlig men används i min erfarenhet relativt sällan i praktiken.
Ser man dessutom till att anropa metoder på interfacen enligt DI (kan knappt se hur man gör för att inte följa det längre...), och inte nånsin referera till en konkret implementation så har man nästan garanterat bra "testbarhet" också.
(Konkret = kod =D)