Eine kleinen Sinn mag das ganze evlt. ergeben. Wenn du es aus Sicht der Komponentenverwaltung betrachtest. Denn du verlagerst das ganze an einen Zentralen Punkt in deiner Applikation. Aber über DI wird in letzter Zeit sowieso viel gestritten. Denn oft wird DI als Factory für Objekte mit Singletoncharakter verwendet. Singleton sind nichts anders als globale variablen. Also ist das auch schon wieder mit Vorsicht zu genießen.
Du kannst aber meiner Meinung nach im ersten Schritt bedenkenlos das gane in deiner App-Main konfigurieren und dann zu gegebenem Zeitpunkt X wo anders hin verlagern. Du könntest z.B. eine weitere Assembly bauen, die deine Konfiguration vornimmt, gegen die du referenzierst. Also ein Interface zum Mappen.
Irgendwo musst du ja dein Mapping vornehmen. Ob das app.config, irgendeine neuemodisch Skriptsprache auf Basis der DLR oder eine weitere C# Assembly ist, macht hier nichts aus.
Ob du nun DI per Hand machst oder per IoC-Container will ich mal aussen vor lassen. DI ansicht ist auch nur eine Symptomkur. Das eigentliche Problem ist die Lose Kopplung und Kommunikation von Komponenten. Martin Fowler beschreibt es in seinem Fazit über IoC und DI eigentlich auch genauso. Das Problem ist die Konfiguration deiner Services. Ralf Westphal hat ja da seine bevorzugte Architektur mit dem XcoAppSpace bzw. ganz neu den Event-Based Komponents, das im Prinzip, so wie ich das verstehe auch einem Nachrichtenbus entspricht, nur eben "sexy".
Das Problem ist im Grunde für mich immer das gleiche. Ich habe Komponenten, die Schnittstellen haben, also wiederverwendet werden können. Wie schaffe ich nun die Konfiguration dieser Schnittstellen durchzuführen?
1. Dynamischer Code: Nachteil: keine Typsicherheit. Vorteil: Komponenten können zur Laufzeit getauscht werden)
2. Statischer Code: Nachteil: Fest verdrahtet, Kompontenten müssen zur Compilezeit bekannt sein. Vorteil: Typsicherheit. Contract kann zur Compilezeit garantiert werden.
AOP mit dem Aspektweaving gibts ja in seinen beiden Formen. Service Konfiguration ist ein anderer Ansatz. Aber zum Schluss bleibt es immer noch offen. Wo findet diese Konfiguration statt.
Ein weiterer Ansatz ist ein dynamischer mit Typsicherheit. In Boo oder F# (oder ab .NET 4.0) gibt es das Interface IStructuralEquatable das auf die gleichheit der Werte innerhalb einer Klasse/Struktur schaut. (Wird für das Ducktyping verwendet). Damit bindest du ein Protokoll ein. Du schaust nach, ob deine Klasse Methode A, B und C einbindet und nimmst dann einfach diese um es auszuführen. Das ist aber auch nicht ganz so typsicher. Entspricht dann einem Patternmatching auf Objektebene. (Hoffe das verwirrt jetzt nicht zu sehr).
Mache Entwickler sind früher dazu übergegangen Konventionen auf zu stellen. Aber wir wissen ja "configuration over convention". Also überleg dir weiter, was dir lieber ist. Du solltest aber sowieso keine App bauen, die alle Abhängigkeiten zentral in einem Container verwaltet. Nimm dir z.B. MEF und verwalte damit einzelne Komponenten, oder einen Container mit Childcontainer. StructureMap kann das laut Björn Rochel ganz gut. Siehe dieser Beitrag. Da gehts nach dem Beitrag in der Diskussion darum, ob die Funktionalität die StructureMap bietet nicht auch ausreicht. In folgendem Post beschreibt er eine Funktion von StructureMap das dem Reflection nahe kommt. Es wird als eine Convention zum Konfigurieren erstellt. Komische Bezeichnung.
Warum machen wir das alles? Um nicht in einem ContainerSpaghetti-Code zu landen. Denn als Hinweis: IOC-Container sind erfunden worden um den SpaghettiCode zu beseitigen und nicht einen neuen zu erzeugen.
Probier mal eine App mit 50 Komponenten aus. Kannst du mir versprechen, dass da jede Komponente überall gebraucht wird? Ich werde demnächst auch mal anfangen eine kleine App mit MEF und IOC zu mische. So enstehen klenie funktionale Parts die ihrerseits mit IOC konfiguriert werden. Diese Parts können dann in anderen Applikationen erneute eingestetzt werden.
Die Strukturierung von DI sollte also so aussehen: Jeweils kleine Container für die Micro-Configuration und einen Container für die Architekturelle Configuration, also dem zusammenschalten der "Micro-Controller" (schönes Wortspie l
). Das ist mein jetziger Stand der Dinge.