Vraag Wat is afhankelijkheid injectie?


Er zijn al verschillende vragen geplaatst met specifieke vragen over afhankelijkheid injectie, zoals wanneer te gebruiken en welke kaders er voor zijn. Echter,

Wat is afhankelijkheidsinjectie en wanneer / waarom zou het wel of niet moeten worden gebruikt?


2626
2017-09-25 00:28


oorsprong


antwoorden:


Kortom, in plaats van dat uw objecten een afhankelijkheid creëren of een fabrieksobject vragen om er een voor hen te maken, geeft u extern de benodigde afhankelijkheden door aan het object en maakt u het een ander probleem. Dit 'iemand' is een object verderop in de afhankelijkheidsgrafiek of een afhankelijkheidsinjector (framework) waarmee de afhankelijkheidsgrafiek wordt opgebouwd. Een afhankelijkheid zoals ik deze hier gebruik, is elk ander object waarnaar het huidige object moet verwijzen.

Een van de grote voordelen van afhankelijkheidsinjectie is dat het testen veel eenvoudiger kan maken. Stel dat je een object hebt dat in zijn constructor zoiets doet als:

public SomeClass() {
    myObject = Factory.getObject();
}

Dit kan lastig zijn als u alleen eenheidsstests uitvoert op SomeClass, vooral als myObject iets is dat complexe schijf- of netwerktoegang biedt. Dus nu ben je aan het kijken naar mijnObject, maar ook om de fabrieksoproep te onderscheppen. Hard. Geef in plaats daarvan het object door als argument aan de constructor. U hebt het probleem nu elders verplaatst, maar testen kan veel eenvoudiger worden. Maak gewoon een dummy myObject en geef dat door. De constructeur ziet er nu een beetje uit als:

public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

Dit is een stijl van afhankelijkheidsinjectie - via de constructor. Verschillende mechanismen zijn mogelijk.

  • Zoals opgemerkt in de opmerkingen, is een veelgebruikt alternatief om een ​​do-nothing constructor te definiëren, en de afhankelijkheden geïnjecteerd te hebben via eigenschappeninstellers (h / t @ MikeVella).
  • Martin Fowler documenteert een derde alternatief (h / t @ MarcDix), waarbij klassen expliciet een interface implementeren voor de afhankelijkheden die ze willen injecteren.

Wanneer er geen afhankelijkheidsinjectie wordt gebruikt (zoals in klassen die te veel werken in hun constructeurs, enz.), Wordt het vaak moeilijker om componenten te isoleren in unit-testen.

In 2013 toen ik dit antwoord schreef, was dit een belangrijk thema op de Google Test Blog. Dit blijft voor mij het grootste voordeel, omdat je misschien niet altijd de extra flexibiliteit in je runtime-ontwerp nodig hebt (bijvoorbeeld voor service locator of soortgelijke patronen), maar je moet vaak wel in staat zijn om je klassen tijdens het testen te isoleren.


1633
2017-09-25 00:49



De beste definitie die ik tot nu toe heb gevonden, is één door James Shore:

"Dependency Injection" is een prijs van 25 dollar   termijn voor een concept van 5 cent. [...]   Afhankelijkheid injectie betekent het geven van een   bezwaar maken tegen de instantievariabelen. [...].

Er bestaat een artikel van Martin Fowler dat kan ook nuttig zijn.

Injectie door afhankelijkheid levert in feite de objecten op die een object nodig heeft (de afhankelijkheden) in plaats van deze zelf te laten construeren. Het is een zeer nuttige techniek om te testen, omdat het toestaat dat afhankelijkheden worden bespot of uitgehold.

Afhankelijkheden kunnen op vele manieren in objecten worden geïnjecteerd (zoals constructeurinjectie of inbrengerinjectie). Men kan zelfs gespecialiseerde afhankelijkheidsinjectiekaders gebruiken (bijvoorbeeld de lente) om dat te doen, maar ze zijn zeker niet vereist. U hebt die kaders niet nodig om afhankelijkheidsinjectie te krijgen. Het expliciet instantiëren en doorgeven van objecten (afhankelijkheden) is net zo goed een injectie als een injectie per kader.


2058
2017-09-26 16:50



Ik vond dit grappige voorbeeld in termen van losse koppeling:

Elke toepassing bestaat uit vele objecten die met elkaar samenwerken om nuttige dingen te doen. Traditioneel is elk object verantwoordelijk voor het verkrijgen van zijn eigen referenties naar de afhankelijke objecten (dependencies) waarmee het samenwerkt. Dit leidt tot sterk gekoppelde klassen en moeilijk te testen code.

Beschouw bijvoorbeeld a Car voorwerp.

EEN Car afhankelijk van wielen, motor, brandstof, batterij, etc. om te gebruiken. Traditioneel definiëren we het merk van dergelijke afhankelijke objecten samen met de definitie van de Car voorwerp.

Zonder Dependency Injection (DI):

class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

Hier de Car voorwerp is verantwoordelijk voor het maken van de afhankelijke objecten.

Wat als we het type afhankelijk object willen veranderen - laten we zeggen Wheel - na de initiaal NepaliRubberWheel() lekke banden? We moeten het Car-object opnieuw maken met zijn nieuwe afhankelijkheid zeg ChineseRubberWheel(), maar alleen de Car fabrikant kan dat doen.

Wat doet de Dependency Injection doen ons voor ...?

Bij het gebruik van afhankelijkheidsinjectie krijgen objecten hun afhankelijkheden tijdens runtime in plaats van compileertijd (autoproductie tijd). Zodat we nu de Wheel wanneer we maar willen. Hier de dependency (wheel) kan worden geïnjecteerd Car tijdens runtime.

Na het gebruik van afhankelijkheidsinjectie:

Hier zijn we injecteren de afhankelijkheden (Wiel en batterij) tijdens runtime. Vandaar de term: Dependency Injection. 

class Car{
  private Wheel wh = [Inject an Instance of Wheel (dependency of car) at runtime]
  private Battery bt = [Inject an Instance of Battery (dependency of car) at runtime]
  Car(Wheel wh,Battery bt) {
      this.wh = wh;
      this.bt = bt;
  }
  //Or we can have setters
  void setWheel(Wheel wh) {
      this.wh = wh;
  }
}

Bron: Inzicht in injectie begrijpen


507
2018-05-22 04:01



Dependency Injection is een praktijk waarbij objecten zo worden ontworpen dat ze instanties van objecten uit andere stukjes code ontvangen, in plaats van ze intern te construeren. Dit betekent dat elk object dat de interface implementeert die vereist is door het object, kan worden vervangen zonder de code te veranderen, wat het testen vereenvoudigt en de ontkoppeling verbetert.

Overweeg deze classen bijvoorbeeld:

public class PersonService {
  public void addManager( Person employee, Person newManager ) { ... }
  public void removeManager( Person employee, Person oldManager ) { ... }
  public Group getGroupByManager( Person manager ) { ... }
}

public class GroupMembershipService() {
  public void addPersonToGroup( Person person, Group group ) { ... }
  public void removePersonFromGroup( Person person, Group group ) { ... }
} 

In dit voorbeeld is de implementatie van PersonService::addManager en PersonService::removeManager zou een exemplaar van de GroupMembershipService nodig hebben om zijn werk te kunnen doen. Zonder afhankelijkheidsinjectie zou de traditionele manier om dit te doen zijn om een ​​nieuw te creëren GroupMembershipService in de constructor van PersonService en gebruik dat instantiekenmerk in beide functies. Echter, als de constructeur van GroupMembershipService heeft meerdere dingen die het vereist, of erger nog, er zijn enkele initialisatie "setters" die moeten worden aangeroepen op de GroupMembershipService, de code groeit vrij snel, en de PersonServicenu hangt niet alleen van de GroupMembershipService maar ook al het andere GroupMembershipService hangt af van. Verder de koppeling naar GroupMembershipService is hard gecodeerd in de PersonService wat betekent dat je "a" niet kunt "dummyen" GroupMembershipService voor testdoeleinden, of om een ​​strategiepatroon te gebruiken in verschillende delen van uw toepassing.

Met afhankelijkheid injectie, in plaats van het instantiëren van de GroupMembershipService in jouw PersonService, zou je het doorgeven aan de PersonService constructor, of voeg een eigenschap (getter en setter) toe om een ​​lokale instance ervan in te stellen. Dit betekent dat jouw PersonService hoeft zich niet langer zorgen te maken over het maken van een GroupMembershipService, het accepteert gewoon diegenen die het heeft gegeven en werkt met hen samen. Dit betekent ook dat alles wat een subklasse is van GroupMembershipService, of implementeert het GroupMembershipService interface kan worden "geïnjecteerd" in de PersonService, en de PersonService hoeft niets te weten over de verandering.


233
2017-09-25 06:49



Het geaccepteerde antwoord is goed - maar ik zou hieraan willen toevoegen dat DI heel erg lijkt op het klassieke vermijden van hardgecodeerde constanten in de code.

Wanneer u een constante gebruikt zoals een databasenaam, verplaatst u deze snel van de binnenkant van de code naar een willekeurig configuratiebestand en geeft u een variabele door die die waarde bevat naar de plaats waar deze nodig is. De reden om dat te doen is dat deze constanten meestal vaker veranderen dan de rest van de code. Bijvoorbeeld als u de code in een testdatabase wilt testen.

DI is hier analoog aan in de wereld van objectgeoriënteerde programmering. De waarden daar in plaats van constante letterlijke waarden zijn hele objecten - maar de reden om de code te verplaatsen om ze uit de klassencode te maken, is vergelijkbaar - de objecten veranderen vaker dan de code die ze gebruikt. Een belangrijk geval waar een dergelijke verandering nodig is, zijn testen.


142
2018-01-06 18:33



Laten we ons voorstellen dat je wilt vissen:

  • Zonder afhankelijkheidsinjectie, moet je alles zelf regelen. Je moet een boot vinden, een hengel kopen, zoeken naar aas, enz. Het is natuurlijk mogelijk, maar het legt een grote verantwoordelijkheid op je. In softwaretermen betekent dit dat je al deze dingen moet opzoeken.

  • Bij afhankelijkheidsinjectie zorgt iemand anders voor de volledige voorbereiding en stelt het de benodigde apparatuur ter beschikking aan u. Je ontvangt ("wordt geïnjecteerd") de boot, de hengel en het aas - allemaal klaar voor gebruik.


96
2017-10-22 04:47



Deze is de meest eenvoudige uitleg over Dependency Injection en Afhankelijkheid injectie container Die ik ooit heb gezien:

Zonder afhankelijkheid injectie

  • Applicatie heeft Foo nodig (bijvoorbeeld een controller), dus:
  • Applicatie maakt Foo
  • Applicatie roept Foo
    • Foo heeft een balk nodig (bijvoorbeeld een service), dus:
    • Foo maakt een balk
    • Foo roept Bar
      • Bar heeft Bim nodig (een service, een repository, ...), dus:
      • Bar maakt Bim
      • Bar doet iets

Met afhankelijkheid injectie

  • Applicatie heeft Foo nodig, die Bar nodig heeft, die Bim nodig heeft, dus:
  • Applicatie maakt Bim
  • Applicatie maakt een balk en geeft deze Bim
  • Applicatie maakt Foo en geeft het een balk
  • Applicatie roept Foo
    • Foo roept Bar
      • Bar doet iets

Een injectie-container voor afhankelijkheid gebruiken

  • Applicatie heeft Foo nodig dus:
  • Toepassing haalt Foo uit de container, dus:
    • Container maakt Bim
    • Container maakt balk en geeft deze Bim
    • Container maakt Foo en geeft het balk
  • Applicatie roept Foo
    • Foo roept Bar
      • Bar doet iets

Dependency Injection en afhankelijkheid Injectiecontainers zijn verschillende dingen:

  • Dependency Injection is een methode om betere code te schrijven
  • een DI-container is een hulpmiddel om afhankelijkheden te injecteren

U hebt geen container nodig om een ​​injectie met afhankelijkheid te doen. Een container kan u echter helpen.


80
2018-05-05 11:53



Laten we een eenvoudig voorbeeld proberen met Auto en Motor klassen, elke auto heeft een motor nodig om overal naartoe te gaan, althans voorlopig. Dus hieronder hoe code eruit zal zien zonder afhankelijkheid injectie.

public class Car
{
    public Car()
    {
        GasEngine engine = new GasEngine();
        engine.Start();
    }
}

public class GasEngine
{
    public void Start()
    {
        Console.WriteLine("I use gas as my fuel!");
    }
}

En om de autoklasse te activeren, gebruiken we de volgende code:

Car car = new Car();

Het probleem met deze code die we nauw hebben gekoppeld aan GasEngine en als we besluiten om het te veranderen in ElectricityEngine, moeten we de autoklasse herschrijven. En hoe groter de toepassing, hoe meer problemen en hoofdpijn we zullen moeten toevoegen en een nieuw type motor moeten gebruiken.

Met andere woorden, met deze benadering is onze klasse Car van hoog niveau afhankelijk van de GasEngine-klasse op een lager niveau die het principe van afhankelijkheid van Inversie (DIP) van SOLID schendt. DIP suggereert dat we afhankelijk moeten zijn van abstracties, niet van concrete klassen. Om dit te bevredigen, introduceren we IEngine-interface en herschrijf code zoals hieronder:

    public interface IEngine
    {
        void Start();
    }

    public class GasEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I use gas as my fuel!");
        }
    }

    public class ElectricityEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I am electrocar");
        }
    }

    public class Car
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)
        {
            _engine = engine;
        }

        public void Run()
        {
            _engine.Start();
        }
    }

Nu is onze autoklasse afhankelijk van alleen de IEngine-interface, niet van een specifieke implementatie van de engine. Nu is de enige truc hoe we een exemplaar van de auto maken en het een echte concrete Engine-klasse zoals Gas Engine of Electricity Engine geven. Dat is waar Dependency Injection komt binnen.

   Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

Hier injecteren (passeren) we in principe onze afhankelijkheid (Engine-instantie) aan Car constructor. Dus nu hebben onze klassen een losse koppeling tussen objecten en hun afhankelijkheden en kunnen we gemakkelijk nieuwe soorten motoren toevoegen zonder de klasse Auto te veranderen.

Het belangrijkste voordeel van de Dependency Injection dat klassen losjes gekoppeld zijn, omdat ze geen hardcoded afhankelijkheden hebben. Dit volgt het principe van de afhankelijkheid van inversie, dat hierboven werd genoemd. In plaats van naar specifieke implementaties te verwijzen, vragen klassen om abstracties (meestal interfaces) die aan hen worden verstrekt wanneer de klas is gebouwd.

Dus uiteindelijk Afhankelijkheid injectie is gewoon een techniek voor   het bereiken van losse koppeling tussen objecten en hun afhankelijkheden.   In plaats van direct de afhankelijkheden in te stellen waar de klas behoefte aan heeft   Om zijn acties uit te voeren, worden afhankelijkheden aan de klas geleverd   (meestal) via constructor injectie.

Ook wanneer we veel afhankelijkheden hebben, is het zeer goed om Inversion of Control (IoC) -containers te gebruiken, die we kunnen vertellen welke interfaces moeten worden toegewezen aan welke concrete implementaties voor al onze afhankelijkheden en we kunnen deze afhankelijkheden voor ons laten oplossen wanneer het wordt geconstrueerd ons doel. We kunnen bijvoorbeeld in de toewijzing voor de IoC-container aangeven dat de IEngine afhankelijkheid moet worden toegewezen aan de Gasmotor klasse en wanneer we de IoC-container vragen om een ​​exemplaar van onze Auto klasse, het bouwt automatisch onze Auto les met een Gasmotor afhankelijkheid doorgegeven.

BIJWERKEN: Volgde onlangs een cursus over EF Core van Julie Lerman en vond ook haar korte definitie over DI.

Injectie van afhankelijkheid is een patroon waarmee uw toepassing kan worden geïnjecteerd   objecten onderweg naar klassen die ze nodig hebben, zonder deze te forceren   klassen om verantwoordelijk te zijn voor die objecten. Het staat je code toe om te zijn   losjes gekoppeld, en Entity Framework Core sluit hier op aan   systeem van diensten.


77
2017-07-06 09:42



Betekent "afhankelijkheidsinjectie" niet alleen het gebruik van geparameteriseerde constructeurs en openbare setters?

James Shore's artikel toont de volgende voorbeelden ter vergelijking.

Constructor zonder afhankelijkheid injectie:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example() { 
    myDatabase = new DatabaseThingie(); 
  } 

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
} 

Constructor met afhankelijkheid injectie:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example(DatabaseThingie useThisDatabaseInstead) { 
    myDatabase = useThisDatabaseInstead; 
  }

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
}

44
2018-05-02 00:40



Wat is Dependixcy Injection (DI)?

Zoals anderen al hebben gezegd, Dependency Injection (DI) verwijdert de verantwoordelijkheid voor directe creatie en het beheer van de levensduur van andere objectinstanties waarvan onze klasse van belang (consumentenklasse) afhankelijk is (in de UML-gevoel). Deze instanties worden in plaats daarvan doorgegeven aan onze consumentenklasse, meestal als constructorparameters of via property setters (het beheer van het afhankelijkheidsobject instancing en doorgeven aan de consumentenklasse wordt meestal uitgevoerd door een Inversion of Control (IoC) container, maar dat is een ander onderwerp).

DI, DIP en SOLID

Specifiek in het paradigma van Robert C Martin's SOLID-principes van Object Oriented Design, DI is een van de mogelijke implementaties van de Dependency Inversion Principle (DIP). De DIP is het D van de SOLID mantra  - Andere DIP-implementaties omvatten de Service Locator en Plugin-patronen.

Het doel van de DIP is om strakke, concrete afhankelijkheden tussen klassen te ontkoppelen en in plaats daarvan de koppeling los te maken door middel van een abstractie, die kan worden bereikt via een interface, abstract class of pure virtual class, afhankelijk van de gebruikte taal en aanpak.

Zonder de DIP is onze code (ik heb deze 'consumerende klasse' genoemd) rechtstreeks gekoppeld aan een concrete afhankelijkheid en wordt hij ook vaak belast met de verantwoordelijkheid om te weten hoe een instantie van deze afhankelijkheid, d.w.z. conceptueel, kan worden verkregen en beheerd:

"I need to create/use a Foo and invoke method `GetBar()`"

Overwegende dat na toepassing van de DIP de vereiste wordt versoepeld, en de zorg om het verkrijgen en beheren van de levensduur van de DIP; Foo afhankelijkheid is verwijderd:

"I need to invoke something which offers `GetBar()`"

Waarom DIP (en DI) gebruiken?

Ontkoppelingsafhankelijkheden tussen klassen op deze manier mogelijk maken gemakkelijke vervanging van deze afhankelijkheidsklassen met andere implementaties die ook voldoen aan de vereisten van de abstractie (de afhankelijkheid kan bijvoorbeeld worden geschakeld met een andere implementatie van dezelfde interface). Bovendien, zoals anderen al hebben gezegd, mogelijk de De meest voorkomende reden om klassen te ontkoppelen via de DIP is om een ​​consumerende klasse afzonderlijk te laten testen, omdat deze dezelfde afhankelijkheden nu kunnen worden uitgewerkt en / of bespot.

Eén gevolg van DI is dat het beheer van de levensduur van afhankelijkheidsobjecten niet langer wordt beheerst door een consumerende klasse, omdat het afhankelijkheidsobject nu wordt doorgegeven aan de consumerende klasse (via de constructor of de injectie van de setter).

Dit kan op verschillende manieren worden bekeken:

  • Als de levensduurcontrole van afhankelijkheden door de consumerende klasse moet worden behouden, kan de controle opnieuw worden ingesteld door een (abstracte) fabriek voor het maken van instanties voor afhankelijkheidsklassen in de consumentenklasse te injecteren. De consument kan exemplaren verkrijgen via een Create indien nodig naar de fabriek, en verwijder deze instanties zodra ze voltooid zijn.
  • Of, levensduurcontrole van afhankelijkheidsinstanties kan worden opgegeven voor een IoC-container (meer hierover hieronder).

Wanneer DI gebruiken?

  • Waar het waarschijnlijk nodig is om een ​​afhankelijkheid te vervangen door een equivalente implementatie,
  • Telkens wanneer u de methoden van een klasse moet testen, los van de afhankelijkheden,
  • Wanneer onzekerheid over de levensduur van een afhankelijkheid experimenten kan rechtvaardigen (bijvoorbeeld Hey, MyDepClass is thread safe - wat als we er een singleton van maken en dezelfde instantie in alle consumenten injecteren?)

Voorbeeld

Hier is een eenvoudige C # -implementatie. Gezien de onderstaande Consuming-klasse:

public class MyLogger
{
   public void LogRecord(string somethingToLog)
   {
      Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
   }
}

Hoewel schijnbaar onschadelijk, heeft het er twee static afhankelijkheden van twee andere klassen, System.DateTime en System.Console, die niet alleen de logging-uitvoeropties beperken (loggen naar console is waardeloos als niemand kijkt), maar erger nog, het is moeilijk om automatisch te testen, gezien de afhankelijkheid van een niet-deterministische systeemklok.

We kunnen echter van toepassing zijn DIP voor deze klasse, door de aandacht voor tijdstempels te abstraheren als een afhankelijkheid en koppeling MyLogger alleen naar een eenvoudige interface:

public interface IClock
{
    DateTime Now { get; }
}

We kunnen ook de afhankelijkheid ervan losmaken Console naar een abstractie, zoals een TextWriter. Dependency Injection wordt meestal ook geïmplementeerd constructor injectie (een abstractie doorgeven aan een afhankelijkheid als een parameter voor de constructor van een consumerende klasse) of Setter Injection (de afhankelijkheid doorgeven via een setXyz() setter of een .Net-property met {set;} bepaald). Constructor Injection heeft de voorkeur, omdat dit garandeert dat de klasse zich in de juiste staat bevindt na de bouw en maakt het mogelijk dat de interne afhankelijkheidsvelden worden gemarkeerd als readonly (C #) of final (Java). Dus met behulp van constructor injectie op het bovenstaande voorbeeld, dit laat ons met:

public class MyLogger : ILogger // Others will depend on our logger.
{
    private readonly TextWriter _output;
    private readonly IClock _clock;

    // Dependencies are injected through the constructor
    public MyLogger(TextWriter stream, IClock clock)
    {
        _output = stream;
        _clock = clock;
    }

    public void LogRecord(string somethingToLog)
    {
        // We can now use our dependencies through the abstraction 
        // and without knowledge of the lifespans of the dependencies
        _output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog);
    }
}

(Een beton Clock moet worden verstrekt, wat natuurlijk kan terugkeren naar DateTime.Nowen de twee afhankelijkheden moeten worden geleverd door een IoC-container via een injectie van een constructor)

Een geautomatiseerde unit test kan worden gebouwd, wat definitief bewijst dat onze logger correct werkt, omdat we nu controle hebben over de afhankelijkheden - de tijd en we de geschreven uitvoer kunnen bespioneren:

[Test]
public void LoggingMustRecordAllInformationAndStampTheTime()
{
    // Arrange
    var mockClock = new Mock<IClock>();
    mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45));
    var fakeConsole = new StringWriter();

    // Act
    new MyLogger(fakeConsole, mockClock.Object)
        .LogRecord("Foo");

    // Assert
    Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString());
}

Volgende stappen

Afhankelijkheid injectie is altijd geassocieerd met een Inversie van bedieningscontainer (IoC), om de concrete afhankelijkheidsinstanties te injecteren (verstrekken) en om instanties voor de levensduur te beheren. Tijdens het configuratie / bootstrappingproces, IoC containers laten toe het volgende te definiëren:

  • afbeelding tussen elke abstractie en de geconfigureerde betonimplementatie (bijv. "op elk moment dat een consument een aanvraag indient IBar, retourneer een ConcreteBar aanleg")
  • beleid kan worden ingesteld voor het beheer van de levensduur van elke afhankelijkheid, b.v. om een ​​nieuw object voor elke consumentensubject te maken, om een ​​singleton-afhankelijkheidsinstantie voor alle consumenten te delen, om dezelfde afhankelijkheidsinstantie alleen in dezelfde thread te delen, enzovoort.
  • In .Net zijn IoC-containers bekend met protocollen zoals IDisposable en neemt de verantwoordelijkheid van Disposing afhankelijkheden in overeenstemming met het geconfigureerde levensduurbeheer.

Wanneer IoC-containers eenmaal zijn geconfigureerd / bootstrapped, werken ze meestal naadloos op de achtergrond, zodat de codeur zich op de betreffende code kan concentreren in plaats van zich zorgen te maken over afhankelijkheden.

De sleutel tot DI-vriendelijke code is om statische koppeling van klassen te voorkomen en geen nieuwe () te gebruiken voor het maken van afhankelijkheden

Zoals in het bovenstaande voorbeeld vereist ontkoppeling van afhankelijkheden enige ontwerpinspanning, en voor de ontwikkelaar is er een paradigmaverschuiving nodig om de gewoonte van newafhankelijkheden rechtstreeks te beheren en in plaats daarvan erop te vertrouwen dat de container de afhankelijkheden beheerst.

Maar de voordelen zijn talrijk, vooral als het gaat om het testen van uw interessecategorie.

Notitie : De creatie / mapping / projectie (via new ..()) van POCO / POJO / Serialization DTO's / Entity Graphs / Anonymous JSON projections et al - d.w.z. "Data only" -klassen of -records - gebruikt of geretourneerd van methoden zijn niet beschouwd als afhankelijkheden (in UML-zin) en niet onderhevig aan DI. Gebruik makend van new om dit te projecteren is prima.


35
2018-04-28 20:17