Wstrzykiwanie zależności dla konkretnego typu

0

Witajcie,

Zacząłem ogarniać sobie owiane grozą i płaczem wstrzykiwanie zależności. Działam z książką "ASP .NET Core MVC 2. Zaawansowane programowanie" Adama Freemana (swoją drogą świetna pozycja, polecam). I o ile bez problemu zrozumiałem sens i działanie wstrzykiwania zależności, jeżeli przygotowujemy implementację interfejsu, czy też łańcuchy zależności o tyle jak napotkałem wstrzykiwanie zależności dla konkretnego typu nie bardzo jestem w stanie znaleźć w czym niby to ma być lepsze od utworzenia tego "normalnie". Gdyby mi ktoś to "po chłopsku" potrafił wytłumaczyć byłbym wdzięczny. Poniżej kody i wdrożenie w temat z książki:

Tworzymy w modelach taki oto plik ProductTotalizer.cs:

using System.Linq;

namespace DependencyInjection.Models
{
    public class ProductTotalizer
    {
        public ProductTotalizer(IRepository repo) => Repository = repo;

        public IRepository Repository { get; set; }

        public decimal Total => Repository.Products.Sum(p => p.Price);
    }
}

Następnie w kontrolerze Home tworzymy zależność od ProductTotalizer:

using Microsoft.AspNetCore.Mvc;
using DependencyInjection.Models;

namespace DependencyInjection.Controllers
{
    public class HomeController : Controller
    {
        private IRepository repository;
        private ProductTotalizer totalizer;

        public HomeController(IRepository repo, ProductTotalizer total)
        {
            repository = repo;
            totalizer = total;
        }

        public ViewResult Index()
        {
            ViewBag.Total = totalizer.Total;
            return View(repository.Products);
        }
    }
}

Na koniec już tylko w Startup'ie dodajemy AddTransient:

services.AddTransient<ProductTotalizer>();

Działanie tego kodu czaję, rozumiem co jest gdzie, dlaczego itp. Tylko nie czaję co daje mi zrobienie tego w ten sposób, zamiast po prostu umieścić tą klasę w kontrolerze.

4

Najprostszy przykład korzyści z używania DI są testy jednostkowe. Te z założenia mają testować wyłącznie daną klasę. Jeżeli tworzyłbyś obiekty wewnątrz tej klasy, to testowałbyś również "niechcący" kod tych zależności. Dobrodziejstwo DI natomiast daje Ci możliwość wstrzyknięcia wydmuszki (Mock), która tylko udaje daną klasę i zwraca zawsze prawidłowe wyniki. Upraszcza to też często pisanie testów, bo nie musisz budować połowy obiektów aplikacji, żeby testowany obiekt w ogóle zadziałał. Nie mówiąc już o zewnętrznych zasobach jak baza danych, komunikacja sieciowa czy zawartość plików. Te też można zmockować a co! :)

Na pewno znalazłyby się bardziej zaawansowane przykłady, gdzie możesz wstrzykiwać różne zależności w różnych kontekstach, ale myślę że ten jeden wystarczy.

0

Okej, teraz ma to sens. Dzięki za pomoc :)

0
CamilloMarcotti napisał(a):

Działanie tego kodu czaję, rozumiem co jest gdzie, dlaczego itp. Tylko nie czaję co daje mi zrobienie tego w ten sposób, zamiast po prostu umieścić tą klasę w kontrolerze.

W tymprzykładzie tego nie widać, ale co jeśli ProductTotalizer miałby trzy zależności, a HomeController miałby 5 takich zależności,z których każda miałaby 3 swoje? Wtedy musiałbyś dać w najgorszym przypadku aż 15 parametrów do kontrolera, aby móc wszystko tworzyć w kontrolerze. Wstrzykiwanie zależności pozwala Ci tego uniknąć.

Sarrus napisał(a):

Nie mówiąc już o zewnętrznych zasobach jak baza danych, komunikacja sieciowa czy zawartość plików. Te też można zmockować a co! :)

A nawet - tylko to jest sens mockować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1