Dependency injection Marko Tošić
Što je dependency injection? Dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle. The term was coined by Martin Fowler. An injection is the passing of a dependency (a service) to a dependent object (a client).
Dependency injection to a 5 year old When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn't want you to have. You might even be looking for something we don't even have or which has expired. What you should be doing is stating a need, "I need something to drink with lunch," and then we will make sure you have something when you sit down to eat. John Munsch - Stackoverflow
Što je dependency injection?
bez DI public SomeClass() { myObject = new Myclass(); } DI public SomeClass (MyClass myObject) { this.myObject = myObject; }
Zašto DI?
Smanjuje povezanost klasa Povećava modularnost i ponovnu iskoristivost koda Kod je lakši za održavanje Omogućava lakše testiranje
3-layer primjer
3-layer primjer (DI)
Tko ima kontrolu?
Composition root Centralno mjesto u aplikaciji gdje se upravlja kompozicijom aplikacije (njenim modulima) Treba biti što bliže ulaznoj točki aplikacije ‐ Console app – Main metoda ‐ MVC app – Application_Start() u Global.asax-u ‐ WebForms – teško integrirati DI
DI proces Register – registracija implementacije s apstrakcijom, događa se jednom pri instanciranju aplikacije Resolve – određivanje ovisnosti, treba biti u jednoj liniji koda Release – otpuštanje ovisnosti, treba biti u jednoj liniji koda
DI process (primjer)
DI patterns Constructor injection – koristi se u većini slučajeva, u konstruktoru se navode sve ovisnosti Method injection – kada moramo ubaciti različite ovisnosti za različite operacije, koristi se npr. kod add-in arhitekture Property injection – setter injection, opcionalni DI, sa lokalnim defaultom
Constructor injection private readonly EngineRepository repository; public CarMaker(EngineRepository repository) { if (repository == null) { throw new ArgumentNullException("repository"); } this.repository = repository; }
DI anti-patterns / refactorings Control Freak Constructor Over-injection – SRP? public MyClass(IUnitOfWorkFactory uowFactory, LoggingProvider loggingProvider, IFooPolicy fooPolicy, IBarService barService, IDoSomeStuff doSomeStuff, IDoMoreStuff doMoreStuff)
DI konfiguracija XML – bez rekompajliranja Code as configuration - najfleksibilniji Auto registration (convention) – ušteda vremena, nije podržan u svim DI containerima
DI funkcionalnosti Object composition Lifetime management Interception (cross-cutting concerns)
Lifetime management Singleton Transient Per Graph Web request context Pooled
Popularni DI/IoC containeri Autofac Castle Windsor nInject StructureMap Unity
Resursi Dependency Injection in.NET, Mark Seeman - originalan članak Martina Fowlera benchmark-performance-comparison - usporedba IoC containera benchmark-performance-comparison