Giusto, prima di tutto, affrontiamo "Qualsiasi codice che chiama il ctor dovrà essere aggiornato quando vengono aggiunte nuove dipendenze"; Per essere chiari, se stai facendo l'iniezione di dipendenza e hai del codice che chiama new () su un oggetto con dipendenze, lo stai facendo in modo sbagliato .
Il tuo contenitore DI dovrebbe essere in grado di iniettare tutte le dipendenze rilevanti, quindi non devi preoccuparti di cambiare la firma del costruttore, quindi quell'argomento non è valido.
Per quanto riguarda l'idea dell'iniezione per metodo vs. per classe, ci sono due problemi principali con l'iniezione per metodo.
Un problema è che i metodi della tua classe dovrebbero condividere le dipendenze, è un modo per assicurarsi che le tue classi siano separate in modo efficace, se vedi una classe con un gran numero di dipendenze (probabilmente più di 4-5), allora quella classe è un candidato principale per refactoring in due classi.
Il prossimo problema è che per "iniettare" le dipendenze, per metodo, dovresti passarle nella chiamata del metodo. Ciò significa che dovrai risolvere le dipendenze prima della chiamata del metodo, quindi probabilmente finirai con un mucchio di codice come questo:
var someDependency = ServiceLocator.Resolve<ISomeDependency>();
var something = classBeingInjected.DoStuff(someDependency);
Ora, supponiamo che chiamerai questo metodo in 10 punti intorno alla tua applicazione: avrai 10 di questi frammenti. Quindi, supponiamo che tu debba aggiungere un'altra dipendenza a DoStuff (): dovrai cambiare lo snippet 10 volte (o racchiuderlo in un metodo, nel qual caso stai semplicemente replicando manualmente il comportamento DI, il che è uno spreco di tempo).
Quindi, ciò che hai praticamente fatto lì è rendere le tue classi che utilizzano DI consapevoli del proprio contenitore DI, il che è una pessima idea , in quanto porta molto rapidamente a un design ingombrante che è difficile da mantenere.
Confrontalo con l'iniezione del costruttore; Nell'iniezione del costruttore non sei legato a un particolare contenitore DI e non sei mai direttamente responsabile per soddisfare le dipendenze delle tue classi, quindi la manutenzione è abbastanza priva di mal di testa.
Mi sembra che tu stia cercando di applicare l'IoC a una classe contenente un sacco di metodi di supporto non correlati, mentre potresti essere meglio suddividere la classe di supporto in un numero di classi di servizio in base all'utilizzo, quindi utilizzare l'helper per delegare il chiamate. Questo non è ancora un ottimo approccio (l'aiutante classificato con metodi che fanno qualcosa di più complesso del semplice trattare gli argomenti che gli vengono passati sono generalmente solo classi di servizio scritte male), ma almeno manterrà il tuo design un po 'più pulito .
(NB: ho seguito l'approccio che stai suggerendo prima, ed è stata una pessima idea che non ho ripetuto da allora. Alla fine stavo cercando di separare le classi che non avevano davvero bisogno di essere separate, e alla fine con una serie di interfacce in cui ogni chiamata di metodo richiedeva una selezione quasi fissa di altre interfacce. È stato un incubo da mantenere.)