Po pierwsze, porozmawiajmy o: „Każdy kod wywołujący ctor będzie wymagał aktualizacji po dodaniu nowych zależności”; Dla jasności, jeśli robisz wstrzykiwanie zależności i masz jakiś kod wywołujący new () na obiekcie z zależnościami, robisz to źle .
Twój kontener DI powinien być w stanie wstrzyknąć wszystkie odpowiednie zależności, więc nie musisz się martwić o zmianę podpisu konstruktora, aby ten argument tak naprawdę się nie utrzymywał.
Jeśli chodzi o ideę wtrysku według metody vs. dla klasy, istnieją dwa główne problemy z wtryskiem według metody.
Jednym z problemów jest to, że metody twojej klasy powinny współdzielić zależności, to jeden ze sposobów, aby upewnić się, że twoje klasy są skutecznie rozdzielone, jeśli zobaczysz klasę z dużą liczbą zależności (prawdopodobnie więcej niż 4-5), to ta klasa jest głównym kandydatem za refaktoryzację na dwie klasy.
Kolejny problem polega na tym, że aby „wstrzyknąć” zależności dla poszczególnych metod, należy przekazać je do wywołania metody. Oznacza to, że będziesz musiał rozwiązać zależności przed wywołaniem metody, więc najprawdopodobniej otrzymasz kilka takich kodów:
var someDependency = ServiceLocator.Resolve<ISomeDependency>();
var something = classBeingInjected.DoStuff(someDependency);
Powiedzmy, że wywołasz tę metodę w 10 miejscach w swojej aplikacji: będziesz mieć 10 takich fragmentów. Następnie powiedz, że musisz dodać kolejną zależność do DoStuff (): będziesz musiał zmienić ten fragment kodu 10 razy (lub owinąć go metodą, w którym to przypadku po prostu replikujesz zachowanie DI ręcznie, co jest marnotrawstwem czasu).
Zatem to, co właściwie zrobiłeś, sprawiło, że twoje klasy korzystające z DI zdają sobie sprawę z własnego kontenera DI, co jest zasadniczo złym pomysłem , ponieważ bardzo szybko prowadzi do trudnego do utrzymania projektu.
Porównaj to z iniekcją konstruktora; W iniekcji konstruktora nie jesteś przywiązany do konkretnego kontenera DI i nigdy nie jesteś bezpośrednio odpowiedzialny za wypełnianie zależności swoich klas, więc utrzymanie jest dość wolne od bólu głowy.
Wydaje mi się, że próbujesz zastosować IoC do klasy zawierającej kilka niepowiązanych metod pomocniczych, podczas gdy lepiej byłoby podzielić klasę pomocniczą na kilka klas usług na podstawie użycia, a następnie użyć pomocnika do delegowania połączenia. To wciąż nie jest świetne podejście (pomocnik klasyfikowany metodami, które robią coś bardziej złożonego niż tylko radzenie sobie z argumentami, które są do nich przekazywane, są zwykle po prostu źle napisanymi klasami usług), ale przynajmniej utrzyma twój projekt trochę czystszy .
(Zauważyłem wcześniej podejście, które sugerujesz, i to był bardzo zły pomysł, którego odtąd nie powtarzałem. Okazało się, że próbowałem wydzielić klasy, które tak naprawdę nie musiały być oddzielone, i ostatecznie skończyłem z zestawem interfejsów, w których każde wywołanie metody wymagało prawie stałego wyboru innych interfejsów. Utrzymanie tego było koszmarem).