Правильно, спочатку давайте розберемося з "Будь-який код, що викликає ctor, потребує оновлення, коли нові залежності будуть додані"; Щоб було зрозуміло, якщо ви робите ін'єкцію залежності і у вас є код, який викликає new () на об'єкт із залежностями, ви робите це неправильно .
Ваш контейнер DI повинен мати можливість вводити всі відповідні залежності, тому вам не потрібно турбуватися про зміну підпису конструктора, так що цей аргумент насправді не відповідає.
Що стосується ідеї щодо введення по методу та по класу, то щодо введення за методом існує дві основні проблеми.
Одне питання полягає в тому, що методи вашого класу повинні розділяти залежності, це один із способів забезпечити ефективне розділення класів, якщо ви бачите клас з великою кількістю залежностей (можливо, більше 4-5), то цей клас є головним кандидатом для рефакторингу на два класи.
Наступне питання полягає в тому, що для того, щоб "ввести" залежності, за методом, вам доведеться передати їх у виклик методу. Це означає, що вам доведеться вирішувати залежності перед викликом методу, тому ви, ймовірно, отримаєте купу такого коду:
var someDependency = ServiceLocator.Resolve<ISomeDependency>();
var something = classBeingInjected.DoStuff(someDependency);
Скажімо, ви збираєтесь зателефонувати за цим способом у 10 місцях вашої програми: у вас буде 10 таких фрагментів. Далі скажіть, що вам потрібно додати ще одну залежність до DoStuff (): вам доведеться змінити цей фрагмент 10 разів (або обгорнути його методом; у такому випадку ви просто реплікуєте поведінку DI вручну, що є марною часу).
Таким чином, те, що ви в основному там зробили, зробило ваші класи, що використовують DI, усвідомлюють власний контейнер DI, що є принципово поганою ідеєю , оскільки це дуже швидко призводить до незграбного дизайну, який важко підтримувати.
Порівняйте це з впорскуванням у конструктор; При конструкторському введенні ви не прив'язані до конкретного контейнера DI, і ви ніколи не несете прямої відповідальності за виконання залежностей своїх класів, тому технічне обслуговування досить не болить головою.
Мені це здається, що ви намагаєтесь застосувати IoC до класу, що містить купу непов'язаних допоміжних методів, тоді як вам може бути краще розділити клас помічника на ряд класів обслуговування на основі використання, а потім використовувати хелпер для делегування дзвінки. Це все ще не чудовий підхід (помічник класифікується з методами, які роблять що-небудь складніше, ніж просто розбиратися з аргументами, які передаються їм, як правило, лише погано написані сервісні класи), але це принаймні збереже ваш дизайн трохи чистішим. .
(NB) Я вже підходив, який ви пропонували раніше, і це була дуже погана ідея, яку я з тих пір не повторював. Виявилося, я намагався відокремити класи, які насправді не потрібно було розділяти, і закінчився з набором інтерфейсів, де кожен виклик методу вимагав майже фіксованого вибору інших інтерфейсів. Це був кошмар.)