Programiranje

Kako uporabiti inverzijo nadzora v C #

Inverzija nadzora in vbrizgavanje odvisnosti vam omogočata, da razbijete odvisnosti med komponentami v vaši aplikaciji in olajšate testiranje in vzdrževanje aplikacije. Inverzija nadzora in vbrizgavanje odvisnosti pa nista enaka - med njima obstajata neznatni razliki.

V tem članku bomo z ustreznimi primeri kode v jeziku C # preučili inverzijo kontrolnega vzorca in razumeli, kako se razlikuje od vbrizgavanja odvisnosti.

Če želite delati s primeri kod v tem članku, morate imeti v sistemu nameščen Visual Studio 2019. Če kopije še nimate, lahko Visual Studio 2019 prenesete tukaj.

Ustvarite projekt aplikacije za konzolo v Visual Studio

Najprej ustvarimo aplikacijski projekt konzole .NET Core v Visual Studio. Ob predpostavki, da je Visual Studio 2019 nameščen v vašem sistemu, sledite spodnjim korakom, da ustvarite nov aplikacijski projekt konzole .NET Core v Visual Studio.

  1. Zaženite Visual Studio IDE.
  2. Kliknite »Ustvari nov projekt«.
  3. V oknu »Ustvari nov projekt« na seznamu predlog izberite »Console App (.NET Core)«.
  4. Kliknite Naprej.
  5. V naslednjem oknu »Konfiguriranje novega projekta« določite ime in mesto novega projekta.
  6. Kliknite Ustvari.

Tako boste ustvarili nov aplikacijski projekt konzole .NET Core v Visual Studio 2019. Ta projekt bomo uporabili za raziskovanje inverzije nadzora v naslednjih odsekih tega članka.

Kaj je inverzija nadzora?

Inverzija nadzora (IoC) je oblikovalski vzorec, pri katerem je krmilni tok programa obrnjen. Inverzijo kontrolnega vzorca lahko izkoristite za ločitev komponent aplikacije, zamenjavo izvedb odvisnosti, posmeh odvisnosti in aplikacijo naredite modularno in preverljivo.

Vbrizgavanje odvisnosti je podskupina načela inverzije nadzora. Z drugimi besedami, vbrizgavanje odvisnosti je le en način izvajanja inverzije nadzora. Inverzijo nadzora lahko na primer izvedete tudi z uporabo dogodkov, delegatov, vzorca predloge, tovarniške metode ali lokatorja storitev.

Inverzija vzorca zasnove krmiljenja navaja, da predmeti ne bi smeli ustvarjati predmetov, od katerih so odvisni za izvajanje neke dejavnosti. Namesto tega bi morali te predmete dobiti od zunanje službe ali zabojnika. Ideja je analogna hollywoodskemu principu, ki pravi: "Ne pokličite nas, poklicali vas bomo." Kot primer bi namesto aplikacije, ki bi klicala metode v okviru, okvir poklical izvedbo, ki jo je zagotovila aplikacija.

Primer inverzije nadzora v C #

Predpostavimo, da gradite aplikacijo za obdelavo naročil in bi radi izvedli beleženje. Zaradi poenostavitve predpostavimo, da je cilj dnevnika besedilna datoteka. V oknu raziskovalca rešitev izberite program konzole, ki ste ga pravkar ustvarili, in ustvarite dve datoteki z imenom ProductService.cs in FileLogger.cs.

  javni razred ProductService

    {

zasebno samo za branje FileLogger _fileLogger = nov FileLogger ();

javni void Log (niz sporočila)

        {

_fileLogger.Log (sporočilo);

        }

    }

javni razred FileLogger

    {

javni void Log (niz sporočila)

        {

Console.WriteLine ("Metoda notranjega dnevnika FileLogger.");

LogToFile (sporočilo);

        }

private void LogToFile (sporočilo v nizu)

        {

Console.WriteLine ("Metoda: LogToFile, Besedilo: {0}", sporočilo);

        }

    }

Izvedba, prikazana v prejšnjem delčku kode, je pravilna, vendar obstajajo omejitve. Omejeni ste na beleženje podatkov samo v besedilno datoteko. Podatkov nikakor ne morete zapisovati v druge vire podatkov ali različne cilje dnevnika.

Neprožna izvedba sečnje

Kaj če bi želeli podatke zapisovati v tabelo zbirke podatkov? Obstoječa izvedba tega ne bi podprla in morali bi spremeniti izvedbo. Lahko spremenite izvedbo razreda FileLogger ali pa ustvarite nov razred, na primer DatabaseLogger.

    javni razred DatabaseLogger

    {

javni void Log (niz sporočila)

        {

Console.WriteLine ("Metoda notranjega dnevnika DatabaseLogger.");

LogToDatabase (sporočilo);

        }

private void LogToDatabase (sporočilo v nizu)

        {

Console.WriteLine ("Metoda: LogToDatabase, Besedilo: {0}", sporočilo);

        }

    }

Lahko celo ustvarite primerek razreda DatabaseLogger znotraj razreda ProductService, kot je prikazano v spodnjem delčku kode.

javni razred ProductService

    {

zasebno samo za branje FileLogger _fileLogger = nov FileLogger ();

zasebno samo za branje DatabaseLogger _databaseLogger =

nov DatabaseLogger ();

public void LogToFile (sporočilo v nizu)

        {

_fileLogger.Log (sporočilo);

        }

public void LogToDatabase (sporočilo v nizu)

        {

_fileLogger.Log (sporočilo);

        }

    }

Vendar, čeprav bi to delovalo, kaj če bi morali podatke aplikacije prijaviti v EventLog? Vaša zasnova ni prilagodljiva in prisiljeni boste spremeniti razred ProductService vsakič, ko se boste morali prijaviti na nov cilj dnevnika. To ni samo okorno, temveč vam bo sčasoma izjemno otežilo upravljanje razreda ProductService.

Dodajte prilagodljivost z vmesnikom

Rešitev te težave je uporaba vmesnika, ki bi ga izvedli konkretni razredi dnevnikov. Naslednji delček kode prikazuje vmesnik, imenovan ILogger. Ta vmesnik bi izvedla dva konkretna razreda FileLogger in DatabaseLogger.

javni vmesnik ILogger

{

void Log (niz sporočila);

}

Posodobljene različice razredov FileLogger in DatabaseLogger so podane spodaj.

javni razred FileLogger: ILogger

    {

javni void Log (niz sporočila)

        {

Console.WriteLine ("Metoda notranjega dnevnika FileLogger.");

LogToFile (sporočilo);

        }

private void LogToFile (sporočilo v nizu)

        {

Console.WriteLine ("Metoda: LogToFile, Besedilo: {0}", sporočilo);

        }

    }

javni razred DatabaseLogger: ILogger

    {

javni void Log (niz sporočila)

        {

Console.WriteLine ("Metoda notranjega dnevnika DatabaseLogger.");

LogToDatabase (sporočilo);

        }

private void LogToDatabase (sporočilo v nizu)

        {

Console.WriteLine ("Metoda: LogToDatabase, Besedilo: {0}", sporočilo);

        }

    }

Zdaj lahko po potrebi uporabite ali spremenite konkretno izvedbo vmesnika ILogger. Naslednji delček kode prikazuje razred ProductService z izvedbo metode Log.

javni razred ProductService

    {

javni void Log (niz sporočila)

        {

ILogger logger = nov FileLogger ();

logger.Log (sporočilo);

        }

    }

Zaenkrat dobro. Kaj pa, če bi radi uporabili DatabaseLogger namesto FileLoggerja v dnevniški metodi razreda ProductService? Izvedbo metode Log lahko spremenite v razredu ProductService, da bo izpolnjeval zahteve, vendar to ne pomeni, da je zasnova prilagodljiva. Zdaj naredimo zasnovo bolj prilagodljivo z uporabo inverzije nadzora in vbrizgavanja odvisnosti.

Obrnite kontrolnik z uporabo vbrizgavanja odvisnosti

Naslednji delček kode ponazarja, kako lahko izkoriščanje vbrizgavanja odvisnosti prenesete primerek razreda konkretnega dnevnika z uporabo vbrizgavanja konstruktorja.

javni razred ProductService

    {

zasebno samo za branje ILogger _logger;

javna ProductService (zapisovalnik ILogger)

        {

_logger = logger;

        }

javni void Log (niz sporočila)

        {

_logger.Log (sporočilo);

        }

    }

Na koncu poglejmo, kako lahko izvedbo vmesnika ILogger prenesemo v razred ProductService. Naslednji delček kode prikazuje, kako lahko ustvarite primerek razreda FileLogger in uporabite injekcijo konstruktorja za posredovanje odvisnosti.

statična praznina Main (string [] args)

{

ILogger logger = nov FileLogger ();

ProductService productService = nova ProductService (zapisovalnik);

productService.Log ("Pozdravljeni, svet!");

}

S tem smo obrnili nadzor. Razred ProductService ni več odgovoren za ustvarjanje primerka izvedbe vmesnika ILogger ali celo za odločitev, katero izvedbo vmesnika ILogger je treba uporabiti.

Inverzija nadzora in vbrizgavanje odvisnosti vam pomagata pri samodejnem ustvarjanju primerov in upravljanju življenjskega cikla vaših predmetov. ASP.NET Core vključuje preprosto, vgrajeno inverzijo kontrolnega vsebnika z omejenim naborom funkcij. Ta vgrajeni vsebnik IoC lahko uporabite, če so vaše potrebe preproste, ali pa uporabite zunanji vsebnik, če želite izkoristiti dodatne funkcije.

Več o tem, kako delati z inverzijo nadzora in vbrizgavanjem odvisnosti v ASP.NET Core, lahko preberete v moji prejšnji objavi tukaj.

$config[zx-auto] not found$config[zx-overlay] not found