Хорошо, во-первых, давайте разберемся с «Любой код, вызывающий 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. Я использовал подход, который вы предлагаете ранее, и это была очень плохая идея, которую я не повторял с тех пор. Оказалось, что я пытался выделить классы, которые действительно не нужно разделять, и в итоге с набором интерфейсов, где каждый вызов метода требовал почти фиксированного выбора других интерфейсов. Это был кошмар для обслуживания.)