Z poprzedniego posta “DI: profesjonalne kontenery” wiemy, że wykorzystujemy kontener. A także, że użycie własnej implementacji to głupota. Pomyśleliśmy również jakimi nad kryteriami wyboru kontenera do naszego projektu.
Tak jak napisałem: ja używam Autofac. I właśnie ta biblioteka wyląduje w przedstawianym demo.
Pierwsze co robię to:
Install-Package Autofac
Mając na pokładzie Autofaca mogę z niego korzystać, zapominając o swoim PoorMansContainer. Autofac jest o tyle ciekawy, że bardzo mocno separuje dwie “fazy” działania kontenera: konfigurację i dostarczanie instancji. Separuje je tak mocno, że do konfiguracji wykorzystuje się osobną, dedykowaną klasę: ContainerBuilder. Konfiguracja w omawianym demie wygląda tak:
static void Main() { var builder = new ContainerBuilder(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); builder.RegisterAssemblyTypes(executingAssembly) .AsSelf() .AsImplementedInterfaces(); // override default registration if needed builder.RegisterType<EmailValidator>() .AsImplementedInterfaces() .SingleInstance(); _container = builder.Build(); }
https://github.com/maniserowicz/di-talk/blob/demo5-start/src/app/WebServer.cs
Widzimy tutaj dwie opcje, których nie posiadał mój własny kontener: automatyczną rejestrację wszystkich klas w aktualnym assembly (RegisterAssemblyTypes) oraz konfigurację EmailValidatora jako Singleton. Proste? Proste. A jakie potężne.
Dodatkowo Autofac oczywiście potrafi po sobie posprzątać:
static void Shutdown() { _container.Dispose(); }
A jak wygląda tworzenie kontrolera? O dziwo, identycznie jak u mnie!
public void RegisterUser(string email) { var controller = _container.Resolve<UsersController>(); controller.RegisterUser(email); }
Ba, mało tego! Nigdzie indziej w całej aplikacji nie zmieniło się NIC! To dzięki zastosowaniu się do “3 calls pattern”, o którym już pisałem (i o którym jeszcze napiszę). Aplikacja ma głęboko gdzieś czy jej kontrolery są rzeźbione mymi rencami pienknymi, czy też przez kontener tworzone “like a pro”.
Oczywiście to co zobaczyliśmy wyżej to jedynie romantyczne liźnięcie możliwości Autofaca samym czubem ozora. Potrafi on o wiele więcej, na przykład rozbić konfigurację kontenera na osobne, “reużywalne” klasy (moduły). Wspiera też interceptory, dzięki czemu możemy pobawić się w AOP bez “tkania” kodu (code weaving) na etapie kompilacji. Ładnie integruje się też na przykład z ASP.NET MVC i kilkoma innymi frameworkami. Ale nie ma sensu, abym to wszystko przepisywał i tłumaczył z angielskiego, odsyłam do bardzo dobrej dokumentacji: https://github.com/autofac/Autofac/wiki.
Jeszcze jedno małe wtrącenie na koniec: na jednym z moich występów zwrócono mi uwagę, że nie mówi się “ałtofak” tylko “ałtofejk”. Nie mogłem wprost w to uwierzyć, więc zapytałem autora, Nicholasa. Okazało się, że przez cały czas mówiłem poprawnie. Żeby jednak nie było wątpliwości i aby poprawna wymowa utkwiła w pamięci narysowałem kalambur utrwalający ten jakże potrzebny w cywilizowanym świecie fakt:
To tyle jeśli chodzi o Autofac. Wiem, przedstawiłem bardzo podstawowe jego zastosowanie, ale być może w przyszłości urodzi się coś bardziej zaawansowanego. Póki co: do następnego razu, kiedy to nadejdzie pora na kilka finalnych refleksji!
DI: użycie Autofac | Maciej Aniserowicz o programowaniu…
Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl…
Użyłeś jawnego odpytywania kontenera o implementację:
var controller = _container.Resolve();
W sieci można znaleźć wiele opinii (nie podzielam ich), że jest to błędne podejście, a jedynym słusznym sposobem na DI jest wstrzykiwanie przez konstruktor (ostatecznie przez własność). A więc kod powinien wyglądać mniej więcej tak:
class JakasKlasa
{
private userscontroller controller;
public JakasKlasa(userscontroller controller)
{
this.Controller = controller;
}
public void RegisterUser(string email)
{
controller.RegisterUser(email);
}
}
Lub tak:
class JakasKlasa
{
Public userscontroller Controller { get; set; }
public void RegisterUser(string email)
{
Controller.RegisterUser(email);
}
}
Oczywiście to nie jest tak że wtedy całkowicie się od AutoFac odcinamy, ponieważ obiekty klasy JakasKlasa nie mogą być już tworzone przez new lecz tylko przez AutoFac. Takie podejście powoduje również, że czasami tworzy się klasy których jedynym celem jest posiadanie konstruktora/własności gdzie AutoFac może coś wstrzyknąć.
Co o tym sądzisz?
RBL,
jak najbardziej, ale GDZIEŚ trzeba się do tego kontenera dobrać : w composition root. A WebServer to u mnie właśnie composition root, więc nie widzę problemu, tam chcę żeby dokładnie tak to wyglądało.
Witam!
Panie Macieju świetna seria postów na temat DI. Jestem początkującym programistą który próbuje sam po godzinach rozwijać się kierunku dobrych praktyk .net (niestety w obecnej pracy nie stosujemy żadnych – powoli je próbuje przemycać :)) Wiele mi te posty rozjaśniły zaciemniając jednocześnie obraz. Mianowicie orientuje się w teorii SOLIDu oraz MVC ale kontenery to dla mnie nowość proszę o wskazówkę (książki, blogi, strony www, jakiś szaman) jak to wszystko połączyć w dobrą całość co kiedy stosować jak stosować, po prostu proszę o wskazówkę gddzie mogę znaleść jakis zbiór dobrej wiedzy jaka stoi za całymi tymi czarami które Pan przedstawił. Dziękuje i pozdrawiam
Tomasz,
To git, cieszę się :). Ta seria jeszcze nie jest zakończona, ale póki co cały czas przeznaczony na “community” zjada mi http://devtalk.pl , konferencje oraz pisanie artykułu. Planuję jeszcze osobnego posta na temat “gdzie czytać dalej o DI”, ale póki co polecam jedyną książkę o Di w .net: http://www.amazon.com/Dependency-Injection-NET-Mark-Seemann/dp/1935182501 .
Dzięki wielkie za namiary na książkę. Jaki książki związane z naszą pracą i z dobrym kodem warto jeszcze przeczytać? Przydałby się jakiś ułożony schemat po co sięgać i w jakiej kolejności dla osób początkujących. Często gęsto słyszymy interesujące hasła ale nie zawsze wiadomo z czym to się je z czym to jest powiązane :) to taka luźna sugestia może pomysł na jakiegoś posta :)
Hej,
Na prezentacji na grupie używałeś ciekawego narzędzia do automatycznego odpalania testów jednostkowych. To była standardowa funkcja nowego VS czy jakiś plugin? Będę wdzięczny za info. Pozdrawiam!
Kodi,
To ncrunch: http://ncrunch.net .
Gadam i piszę o tym od ponad roku, dobrze że coraz więcej osób się nim interesuje bo tool jest mega zacny.
Kosztuje kawałek pieniądza, ale można go wygrać w ostatnim DevTalku :) , jeszcze jest kilka dni: http://devtalk.pl/2014/11/03-o-testach-z-adamem-kosinskim/
O to mi chodziło, dzięki za info :)