Diskuze: Správné použítí
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 14 zpráv z 14.
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Pouzitim new vytvoris zavislost. Proto bys to mel provest skrze kontruktor a spravu instanci ponechat na IOC/DI containeru.
Moc ti děkuji za odpověď uže jsem se pál, že mi nikdo neodepíše. Promiň, ale nevím jak to přesně udělat. Chci potom totiž vytvořit z té třídy DBLogger instanci a mam tam jen jeden konstruktor. A nevím co dát za ten parametr právě...
Koukni treba zde:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
Kouknul jsem a není mi to zcela jasné... Nemohl by jsi mi to prosím ukázat na tom mím příkladu?
Asp neznam, ale v php, kdyz neco pres konstruktor, tak kod asi vypada takto
<?php
class mojeTrida
private $prom;
function __construct()
{
$this->prom = new nejakyjinyObjekt();
$this->prom->login();
}
function __destruct()
{
$this->prom->logout();
$this->prom = null; // nebo free mem
}
Jinymi slovy, ty ten objekt vytvaris v casti var promenne. Coz se muze ukazat
casem jako problem kvuli prehlednosti a mozna i jinak.
U win (delphi, mozna i v asp) tusim misto __construct se pouziva pro class
'mojeTrida' function se stejnym nazvem, 'mojeTrida'.
Destruktor je zase dobre pouzivat k uvolneni pameti prave pro takove pripady,
kdy si tam dovnit class zanasis dalsi objekty. Vsude se pis, jak to dela
automaticky (i php), ale obcas potrebujes pamet uvolnit driv. A kdyz takove
objekty mas v construct, destruct, tak vis, ktere muzes uvolnit. Nemusis je
hledat ve vsech funkcich.
DI sa dá jednoducho chápať tak, že objekt (v tvojom prípade napr. DbLogger) by si nemal sám vytvárať inštancie svojich závislostí (čiže by si v ňom nemal mať žiadne new LogService()), ale dostane ich "odniekiaľ" a sám sa nestará odkiaľ. To odniekiaľ je samozrejme nejaký DI/IoC kontajner alebo niečo podobné a ten sa už líši podľa použitého frameworku. Je to skrátka nejaký objekt alebo trieda, ktorá sa stará o to, aby ostatné objekty v tvojej aplikácii dostali už vytvorené a nakonfigurované závislosti tak, ako potrebujú.
V tvojom príklade by to pri použití constructor injection zjednodušene prebiehalo na spôsob: na nejakej vyššej úrovni v aplikácii vytvorím potrebný logger -> pridám / zaregistrujem ho do IoC kontajnera -> kontajner ním následne "nainštanciuje" objekty, ktoré majú na logger závislosť a požadujú ho cez konštruktor ako parameter. Konkrétna implementácia jednotlivých krokov bude najskôr využívať reflexiu a rozoberať ju tu by bolo na dlhšie.
Samozrejme, je dobrý zvyk závislosti predávať cez interface (čo vidím, že sa snažíš dodržiavať, super), možno ešte dodám, že cez DI by si mal posielať do LogService aj databázu (ak to ešte niekde nerobíš).
A na záver si dovolím zareagovať na príspevok p. Mlicha, aby náhodou nedošlo k nedorozumeniu - v C# sa deštruktory takmer vôbec nepoužívajú, ak potrebuješ pri zániku nejakého objektu uvoľniť tzv. unmanaged resources (napr. spojenia k otvoreným súborom a pod.), tak v tom objekte implementuješ rozhranie IDisposable. Určite vždy uprednostňuj deterministické uvoľnovanie zdrojov cez tento interface pred spoliehaním sa na garbage collector.
Co konkretne ti neni jasne?
Ty nacpes do konstruktoru to co potrebujes a instanci nevytvaris rucne ty pomoci slovicka "new", ale nechas ji vytvorit tak jako v tom tutorialu.
Jj, jak pise Martin Petrovaj, to je vlastne lepsi. Uvnitr bys zadne new delat nemel, pokud se nejedna o struktury pro ukladani dat.
$sql = new sqlPripojeni(...)
$trida = new mojeTrida($sql)
A uvnitr si pak ve tride priradis do promenne objekt z konstruktoru.
function __construct($sql)
{
$this->sql = $sql;
}
vajkuba1234 - protoze je to tam podobne a lepe se mi to vysvetluje nez bych pul dne googloval, jak to prepsat do tohoto jazyka a jeste mozna s vice chybami.
Děkuju všem za odpovědi. Nejvíce mi pomohla od Martin Petrovaj. Chtěl bych se ještě zeptat na to jak si mám posílat i tu DB. Opravdu to mám dělat? Někdy (přesně nevím kdy) jsem četl, že z DB by se měl vytvářet objekt při každé službě, takže to tak není ?
A ještě jedna otázka pokud mám ještě například třídu, která zapisuje log zprávy do souboru mám to taky dát do DI? Nebo jenom třídy co komunikují s db?
1 Nikto ti nebráni vytvoriť si napr. jeden DB kontext napr. pre handlovanie používateľov aplikácie, iný pre veci okolo kategórii a produktov (ak vyvíjaš napr. nejaký eshop) a pod. Neviem ale či je dobrý nápad (a či to vôbec funguje) vytvárať viac rovnakých kontextov (inštancií tej istej triedy odvodenej od bázového DB kontextu, ktoré pristupujú k tým istým dátam a vykonávajú nad nimi CRUD). Aj keby sa to dalo, už len kvôli jednoduchšiemu životu a menej zbytočným problémom by som sa tomu vyhýbal.
Osobne to robievam tak (a viem, že sa to robí dosť často), že z každého druhu kontextu (ak máš na celú aplikáciu jeden, tak fajn) si vytvorím jednu inštanciu (štandardne per request, ale ak voči tomu nemáš odpor a praktické zábrany, teoreticky ti nič nebráni ani v úplnom singletone, aj keď to je téma a problém sám o sebe) a túto inštanciu cez DI dostane každý, kto má na ten kontext závislosť (dependency).
2 Čo sa týka triedy na logovanie správ do súboru, opäť to závisí
hlavne od tvojich potrieb, návrhu a fungovania tvojej aplikácie (a takto je to
v podstate so všetkým ).
Povedal by som ale, že jednoznačne lepší nápad je obdobne ako s databázou
mať len jeden logger a ten (ideálne cez DI) poskytnúť všetkým objektom,
ktoré ho na niečo potrebujú. Budeš mať jednoduchší život pri
konfigurácii toho logovania, keďže ti bude stačiť spravovať to na jednom
mieste a pri jednom loggeri by ti mali odpadnúť potenciálne problémy napr.
so súčasným zápisom do súboru z viacerých loggerov. Aj keby s tým v
jednovláknovej aplikácii bolo problémov menej, stále IMO skončíš s
výkonovo efektívnejším riešením.
Super moc ti děkuju. Fakt bezvadně vysvětleno.
Zobrazeno 14 zpráv z 14.