injecție Dependență (injecție dependență) - documentația de bază 1
ASP.NET Core sprijină injecție de dependență. aplicatii ASP.NET Core folosesc cadru de servicii integrate, care sunt încorporate în metodele de clasă de pornire, și serviciile de aplicații pot fi configurate pentru DI. Containerul implicit de servicii oferă un set minim de caracteristici și nu înlocuiește alte recipiente.
Injectarea Dependență (DI) - o tehnologie care este utilizată la maximum pentru a împărți obiecte și dependențe. Mai degrabă decât montarea directă a componentelor sau utilizarea de link-uri statice, obiecta că clasa are nevoie pentru a efectua o acțiune, având în vedere această clasă într-un mod diferit. Cele mai frecvente clase de dependență de stat prin intermediul constructorului, permițându-le să urmeze principiul dependențelor explicite. Această abordare este cunoscută sub numele de „injecție constructor“.
În cazul în care clasele folosesc DI, componentele lor nu depind unul de altul în mod direct. Aceasta se numește Principiul Dependență inversiune. care prevede că „un module de nivel înalt nu ar trebui să depindă de module de nivel scăzut -. și ambele ar trebui să depindă de abstracții“ În loc de a folosi implementari specifice, cere clasele de abstractizare (de obicei Interface), care le sunt furnizate după crearea. Eliminarea interfețe dependențe și implementări de transmisie ale acestor interfețe ca parametri este, de asemenea, un model de design exemplu de strategie.
În cazul în care sistemul utilizează DI, atunci când multe clase sunt folosite în funcție de constructor (sau proprietăți), este util pentru anumite clase au fost legate de dependențele necesare. Aceste clase sunt numite containere. ei, de asemenea, numit Inversarea container de control (IOC) sau containere DI. Container - este, în principiu, fabrica care furnizează instanțe ale tipurilor necesare. Dacă aveți acest tip de dependență, precum și containere existente pentru furnizarea acestor relații, dependențe vor fi create ca parte a instanței solicitate. În acest fel, dependențe complexe Oferă clasă fără obiect greu de codare. Mai mult, containerele gestionează în mod obișnuit ciclul de viață al obiectului în cadrul aplicației.
ASP.NET Core include un recipient simplu încorporat (reprezentat prin interfața IServiceProvider), care implicit suportă injectare constructor și ASP.NET oferă anumite servicii prin DI. ASP.NET container funcționează cu ambele tipuri de servicii. Mai târziu, în acest articol, serviciile pe care le numim tipuri, care sunt gestionate de IoC container ASP.NET Core. Puteți ajusta serviciile de containere încorporate folosind metoda ConfigureServices Clasa de pornire.
În acest articol, ne uităm la modul în care dependența de injecție se aplică în toate aplicațiile ASP.NET. Dependență Injectarea în MVC este abordată în articolul dependența de injecție și controlere
class ConfigureServices Metoda Startup definește serviciile care urmează să fie utilizate în cerere, inclusiv funcțiile platforme precum Entitate cadru Core și ASP.NET Core MVC. Inițial IServiceCollection. care este ConfigureServices transmise. Există doar câteva servicii. Aici este un exemplu de cum să adăugați servicii suplimentare la container prin intermediul unor astfel de metode de extensie ca AddDbContext. AddIdentity și AddMvc.
Funcții și ASP.NET middleware utilizează o metodă de addService expansiune. să înregistreze toate serviciile care necesită această caracteristică.
Puteți solicita servicii specifice prin metode de pornire. Cm. Rulați aplicația.
Puteți configura aplicația astfel încât să utilizeze diferitele funcții ale cadrului, și puteți lucra cu ConfigureServices. să creeze propriile servicii.
Puteți înregistra propriile servicii. Primul tip este un tip generic (de obicei, interfața), care va fi solicitată din container. Al doilea tip generic este un tip specific de container specimen și care vor fi utilizate pentru a efectua astfel de cereri.
Fiecare apel services.Add
Metoda AddTransient asociază abstract cu anumite tipuri de servicii, dintre care un exemplar este generat pentru fiecare entitate care le solicită. Acest lucru este cunoscut sub numele de ciclul de viață al serviciului. Este important de a alege ciclul de viață adecvat pentru serviciul pe care îl înregistrați. În cazul în care o nouă instanță a serviciului furnizat fiecărei clase care îl solicită? În cazul în care se utilizează o nouă instanță în întreaga interogare? În cazul în care o instanță utilizată în timpul ciclului de viață al aplicației?
În exemplul pentru acest articol, există un CharacterController controler. Metoda lui Index arată lista actuală de caractere și inițializează colectarea, dacă există încă. Deși această aplicație utilizează cadrul entității și clasa ApplicationDbContext. ele nu sunt vizibile în controler. În schimb, un mecanism pentru a avea acces la datele specifice „ascunde“ în spatele interfață ICharacterRepository. care urmează Repository model. ICharacterRepository exemplu solicitat de proiectant și este atribuit câmpul închis, care este apoi utilizat pentru a accesa caracterul dorit.
ICharacterRepository definește două metode, care sunt necesare pentru ca operatorul să lucreze cu instanțe caractere.
Interfața este implementată folosind un anumit tip de CharacterRepository.
Metoda, care este utilizat cu clasa DI CharacterRepository este modelul comun, și aveți posibilitatea să urmați-l pentru a lucra cu toate serviciile - nu numai în „magazia“ sau clase de acces la date.
Rețineți că solicitările CharacterRepository către proiectantul ApplicationDbContext. Adesea, dependența de injecție este utilizată în lanțul, adică, fiecare dependență cere poate cere propria lor dependență. Containerul este responsabil pentru utilizarea tuturor dependențele din copac și returnează servicii complete.
Creați obiectul solicitat și toate obiectele de care are nevoie, de multe ori numit graficul de obiecte. În mod similar, un set de dependență legate este numit un arbore de dependențe sau un grafic de dependență.
În acest caz, ICharacterRepository ApplicationDbContext și trebuie să fie înregistrate cu containerul de serviciu în ConfigureServices de pornire. ApplicationDbContext configurată folosind metoda AddDbContext extensie
Contextul cadru Entitatea trebuie să fie adăugate la containerul de serviciu prin intermediul Scoped. Acest lucru se întâmplă în mod automat dacă utilizați metodele helper, așa cum este arătat mai sus. Repozitorii sunt utilizate cu Entity Framework, ar trebui să aibă același ciclu de viață.
Fiți atenți atunci când se utilizează serviciul Scoped din Singleton. Dacă se întâmplă acest lucru, vom deservi o stare incorectă în procesarea cererilor ulterioare.
Servicii ASP.NET pot fi configurate prin următoarele cicluri de viață:
Transient tranzitorii Serviciile sunt create de fiecare dată când sunt solicitate. Acest ciclu de viață este cel mai bine potrivite deosebit de semnificativ, servicii „ușoare“. Scoped Scoped-servicii sunt create pentru fiecare solicitare. Singleton Singleton-servicii sunt create o dată, la cerere, și apoi fiecare cerere ulterioară utilizează aceeași instanță. În cazul în care aplicația necesită o Singleton, atunci când containerul de serviciu gestionează ciclul de viață al unui serviciu, ar trebui să pună în aplicare modelul Singleton și de a gestiona ciclul de viață al obiectului în clasă.
Serviciile pot fi înregistrate prin intermediul containerului în diverse moduri. Am văzut deja cum să se înregistreze un serviciu de acest tip, prin specificarea unui anumit tip, care va fi utilizat. În plus, puteți utiliza fabrica, care va crea apoi instanța dorită. O a treia abordare este să specificați în mod direct o instanță de tipul corect, și apoi containerul nu încearcă niciodată să creeze o instanță.
Pentru a vă arăta diferența dintre înregistrarea ciclurilor de viață și opțiuni, vom folosi o interfață simplă, care oferă una sau mai multe sarcini într-o tranzacție cu un identificator unic, OperationID. În funcție de modul în care ne-am creat ciclul de viață al serviciului, containerul va da aceleași sau diferite instanțe ale acestei clase de serviciu dorit. Pentru a face clar ceea ce se cere ciclul de viață, vom crea un singur tip pentru fiecare din ciclul de viață:
De asemenea, vom pune în aplicare toate aceste interfețe folosind clasa de operare. care ia Guid de constructor sau creează un nou Guid. în cazul în care acestea nu există.
Mai mult, în fiecare tip ConfigureServices adăugat la proiectant în funcție de ciclul zhiznenngogo respectiv:
Rețineți că IOperationSingletonInstance utilizează un ID de instanță Guid.Empty. așa că va fi gol atunci când se utilizează acest tip. De asemenea, am înregistrat OperationService. care depinde de alte tipuri de operare. așa că va fi gol într-o interogare în cazul în care serviciul devine aceeași instanță ca și operator sau altul pentru a primi diferite tipuri de operațiuni.
Pentru a vă arăta ciclul de viață al obiectului în interiorul și între diferite cereri în cerere, am inclus un exemplu OperationsController. care solicită pentru toate tipurile de stil IOperation. și OperationService. Metoda de acțiune Index apoi afișează toate valorile OperationId controlere și servicii.
Acum vom face două interogări separate la metoda acțiunii controlerului:
![injecție Dependență (injecție dependență) - documentația de bază 1 (dependență) injecție Dependență (injecție dependență) - documentația de bază 1](https://webp.images-on-off.com/25/775/434x266_6v892lho2712koh65mza.webp)
![injecție Dependență (injecție dependență) - documentația de bază 1 (introducere) injecție Dependență (injecție dependență) - documentația de bază 1](https://webp.images-on-off.com/25/775/434x266_ahec3nd08a6ajx7ntrb5.webp)
A se vedea modul în care valorile OperationId diferă atunci când vi se solicită și între interogări.
- obiecte Transient sunt întotdeauna diferite; o nouă instanță a controlerului este furnizat pentru fiecare serviciu.
- Obiectele scoped sunt întotdeauna aceleași atunci când aceeași interogare, dar diferă pentru diferite interogări.
- Singleton obiecte sunt aceleași pentru fiecare interogare, și pentru fiecare obiect.
Servicii disponibile la cerere ASP.NET HttpContext. incluse în RequestServices.
Colecția RequestServices reprezintă serviciile pe care îl configurați și solicită ca o parte a aplicării lor. Atunci când obiectele sunt specificate în funcție, au nevoie tipurile de RequestServices. în loc de ApplicationServices.
În general, nu ar trebui să utilizați aceste proprietăți în mod direct, dar ar trebui să solicite în schimb tipul pe care doriți de clasă, constructorul și lăsați-cadru să pună în aplicare aceste dependențe. Aceste clase sunt mai ușor de testare (a se vedea. Testarea), și nu depind unul de altul.
În aplicațiile aproape întotdeauna RequestServices fi utilizate. și, în orice caz, nu aveți acces la aceste proprietăți direct. În schimb, cere serviciile necesare prin intermediul constructorului de clasă.
Și dacă în clasele prea mult de injecție de dependență? De obicei, acest lucru înseamnă că clasa ta este prea supraîncărcat și încalcă principiul SRP - principiul unic responsabilitate. Ar trebui să modificați această clasă, se deplasează unele dintre funcțiile sale la noua clasă. Rețineți că clasele Controler trebuie să se concentreze pe interfața cu utilizatorul, astfel încât normele de afaceri și accesul la datele ar trebui să fie stocate în clase, în conformitate cu repartizarea responsabilităților.
În ceea ce privește accesul la date, puteți implementa în controlerul DbContext (dacă ați adăugat FE în ConfigureServices servicii de containere). Unii oameni preferă să utilizeze o interfață de depozit, în loc de încorporarea direct DbContext. Folosind interfața pentru a încapsula logica acces la date într-un singur loc poate reduce numărul de locuri în cazul în care aveți de a face modificări în cazul în care există modificări în baza de date.
Servicii integrate are nevoie de containere mânere cadru de bază. Cu toate acestea, dezvoltatorii pot înlocui cu ușurință alt recipient. De obicei, metoda ConfigureServices returneaza un vid. dar în cazul în care a fost modificat astfel încât să se întoarcă IServiceProvider. este posibil să se adapteze și să se întoarcă la un alt recipient. Există mai multe containere IOC disponibile pentru NET. Vom încerca să adăugați o trimitere la punerea în aplicare a containerelor DNX. Acest exemplu utilizează pachetul Autofac.
În primul rând, se adaugă containerele corespunzătoare în pachetele dependențelor de proprietate în project.json:
Apoi, setați containerul în ConfigureServices și a reveni IServiceProvider: