Beim Erstellen einer designierbaren .NET-Komponente müssen Sie einen Standardkonstruktor bereitstellen. Von der IComponent Dokumentation:Kombinieren von gestaltbaren Komponenten mit Abhängigkeitsinjektion
eine Komponente zu sein, muss eine Klasse die IComponent-Schnittstelle implementieren und eine grundlegende Konstruktor, keine Parameter oder einen einzelnen Parameter des Typs IContainer erfordert.
Dies macht eine Abhängigkeitsinjektion über Konstruktorargumente unmöglich. (Extra-Konstrukteuren zur Verfügung gestellt werden könnte, aber der Designer würde sie ignorieren.) Einige Alternativen wir unter Berücksichtigung
Service Locator
Verwenden Sie Dependency Injection nicht, sondern das Muster Service Locator verwenden Abhängigkeiten erwerben. Dies scheint IComponent.Site zu sein. GetService ist für. Ich denke, wir könnten eine wiederverwendbare ISite-Implementierung (ConfigurableServiceLocator?) Erstellen, die mit den notwendigen Abhängigkeiten konfiguriert werden kann. Aber wie funktioniert das im Designer-Kontext?
Dependency Injektion über Eigenschaften
Injekt Abhängigkeiten über Eigenschaften. Stellen Sie Standardinstanzen bereit, wenn sie erforderlich sind, um die Komponente in einem Designer anzuzeigen. Dokumentieren Sie, welche Eigenschaften eingegeben werden müssen.
Inject Abhängigkeiten mit einer Initialize-Methode
Dies sind ähnlich wie Injektion über Eigenschaften, aber es hält die Liste der Abhängigkeiten, die an einem Ort injiziert werden müssen. Auf diese Weise wird die Liste der erforderlichen Abhängigkeiten implizit dokumentiert, und der Compiler unterstützt Sie bei Fehlern, wenn sich die Liste ändert.
Eine Idee, was die beste Praxis ist hier? Wie machst du das?
bearbeiten: Ich habe entfernt „(zum Beispiel ein WinForms Usercontrol)“, da ich die Frage nach Komponenten im Allgemeinen sein soll. Bei den Komponenten dreht sich alles um die Inversion der Kontrolle (siehe Abschnitt 8.3.1 der UMLv2 specification). Ich denke also nicht, dass "Sie keine Dienste injizieren sollten", ist eine gute Antwort.
bearbeiten 2: Es dauerte einige Spiele mit WPF und dem MVVM Muster Antwort Mark, um endlich "get". Ich sehe jetzt, dass visuelle Kontrollen tatsächlich ein Sonderfall sind. Was die Verwendung nicht visueller Komponenten auf Designeroberflächen anbelangt, ist das .NET-Komponentenmodell meiner Ansicht nach grundsätzlich nicht mit der Abhängigkeitsinjektion kompatibel. Es scheint stattdessen um das Service-Locator-Muster herum angelegt zu sein. Möglicherweise wird sich dies mit der Infrastruktur ändern, die in .NET 4.0 im Namespace System.ComponentModel.Composition hinzugefügt wurde.
Wenn ich Ihre Antwort richtig interpretiere, sagen Sie, dass Kontrollen keine Dienste verwenden sollten. Ich bin mir nicht sicher, ob ich dem zustimme. Zum Beispiel habe ich ein Steuerelement, das Text nicht direkt durch den Aufruf von System.Windows.Forms.TextRenderer rendert. Stattdessen verwendet es einen injizierbaren ITextRenderer-Dienst (mit im Wesentlichen den gleichen Methoden). Dies ermöglicht es mir, ausgefallene Abkürzungsstrategien zu implementieren, die über die Möglichkeiten des .NET-Frameworks hinausgehen, während der Code unabhängig von der Steuerung selbst gehalten wird. –
Ja, ich sage, dass Controls keine Dienste verwenden sollten - Dienste sollten Controls verwenden. Ein Steuerelement sollte nur UI rendern. Es ist in Ordnung, dass Sie komplizierte Abkürzungsstrategien einfügen können, aber eine solche Logik gehört in das (Ansichts-) Modell, nicht in die Ansicht selbst. Sie können dann Ihre View an Eigenschaften im Modell binden, die die gewünschten Werte erzeugen, indem Sie die injizierten Abhängigkeiten aufrufen. Auch wenn Sie WinForms zu verwenden scheinen, finden Sie hier Informationen zur Inspiration: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx –