1

Ich habe ein Szenario, in dem ich eine einzelne Instanz einer Komponente im Container registrieren möchte, aber leider nicht beim Start der Anwendung erstellt werden kann. Diese Komponente konnte nur instanziiert werden, indem einige Objekte übergeben wurden, die erst etwas später im Anwendungslebenszyklus verfügbar sind (sie sind jedoch keine anderen IoC-registrierten Dienste). [siehe Hinweis unten].Registrierung in IoC-Container nach der anfänglichen Konfiguration

  • Ist die Registrierung einer Komponente in einem IoC Behälter nach die Erstkonfiguration (in App-Start ausgeführt) eine schlechte Praxis?
  • Wie es ohne direkte Bezugnahme auf den Container zu erreichen? Soll ich einen Registrierungsdienst abstrahieren?
  • Gibt es einen besseren Ansatz, um das Szenario zu unterstützen?

Hinweis über das aktuelle Szenario
Die Komponente Ich mag würde in dem Behälter setzen mit einer bestimmten Instanz eines UI-Steuerelement initialisiert wird (es ist im Grunde ein Adapter), daher muß ich Erstellen Sie die Komponenteninstanz manuell und registrieren Sie sie im Container.
Ich hätte dies beim Start der Anwendung getan, aber leider habe ich die UI Control Instanz noch nicht verfügbar (noch kann ich es selbst erstellen).
Auch zu einem späteren Zeitpunkt kann ich die UI-Steuerungsinstanz nicht von der Oberfläche anderer Komponenten erreichen, ohne ihre konkrete Klasse zu kennen.
Aus diesem Grund dachte ich, ich könnte die Verantwortung für die Adapterregistrierung in die Klasse übernehmen, die die UI-Steuerung besitzt.

Mein erstes Szenario:

public interface IDockManager { ... } 
public class AcmeDockManagerAdapter : IDockManager { 
    public AcmeDockManager(DockControl control) { ... } 
    ... 
} 

public class ShellViewModel { ... } 
public class ShellView : Window { 
    internal DockControl theDockControl; 
} 

public class AnotherViewModel { 
    AnotherViewModel(IDockManager dockManager) { ... } 
} 

Die Lösung Ich bin unconfortable mit:

public class ShellView : Window { 
    internal DockControl theDockControl; 
    public ShellView() { 
     InitializeComponents(); 
     var dockManager = new AcmeDockManagerAdapter(theDockControl); 
     //registration in the container 
    } 
} 

Antwort

1

Sie könnten einen "lazy-Wrapper" statt registrieren. Ein solcher Wrapper implementiert dieselbe Schnittstelle und kann sofort instanziiert werden, verschiebt aber intern die Erstellung der eigentlichen Komponente, die die Arbeit erledigt. Werfen Sie einen Blick auf das Beispiel von ploeh LazyOrderShipper oder LazyOrderShipper2.

bearbeiten: Wenn ich richtig verstehe, versuchen Sie nur, Ihre Ansichten zu Ihren Viewmodels, MVVM-Stil zu verbinden. Ich bevorzuge es, den Container die Viewmodel-Konstruktion handhaben zu lassen, aber die View-Konstruktion und Viewmodel-Verkabelung selbst vorzunehmen. Mein Start-up-Code woul wie folgt aussehen:

var mainViewModel = container.Get<MainViewModel>(); 
var mainView = new MainView(mainViewModel); 
Application.Run(mainView); 

Und im Inneren des MainView Konstruktor würde ich von Kind Kontrollen kümmern, die ihre eigenen Ansichtsmodell erfordern:

public MainView(MainViewModel viewModel) 
    { 
     // link "subviews" to "subviewmodels" 
     this.SomeChildControl.ViewModel = viewModel.SomeChildViewModel; 

     // normal MVVM property wiring 
     viewModel.TitleChanged += delegate { this.Text = viewModel.Title; }; 
     ... 
    } 

Wenn Sie genau das MVVM Ansatz folgen , dann sollten Sie keine Ansicht mit dem Container registrieren müssen. Alles, was "mit der Ansicht sprechen muss", muss stattdessen mit dem zugrunde liegenden Ansichtsmodell sprechen. (Die Dinge werden interessanter, wenn Sie Plug-in-Ansichten in der Benutzeroberfläche mit Registerkarten oder im GUI mit angedockten Fenstern zulassen möchten, aber das ist eine andere Geschichte.)

+0

Dies ist eine sehr elegante Lösung. Mein Problem bezieht sich jedoch nicht auf die Kosten der Komponenteninstanziierung, sondern auf die Verfügbarkeit einiger Konstruktorargumente. Das Verzögern der tatsächlichen Instanziierung erfordert, dass zumindest der träge Wrapper weiß, wie die erforderlichen Argumente abgerufen werden, wenn es schließlich zum Zeitpunkt des Erstellens der Instanz kommt. Ich hätte mein Szenario näher erklären sollen, vielleicht (was ich tun werde). Danke für Ihre Hilfe. –

+0

Entschuldigung, aber die Frage bezieht sich nicht auf die Verkabelung zwischen Ansichten und VMs (die bereits vorhanden ist). Ich fügte nur die tatsächlich beteiligten Klassen hinzu, in der Hoffnung, den Kontext zu verdeutlichen. Mein Wille ist es, den Docking-Teil zu abstrahieren und seine Schnittstelle von ShellVM zu trennen, genau für den Zweck, dynamisches Hinzufügen zu ermöglichen. Ich hätte gerne den Docking-Dienst in den Container gelegt, um die Dependency-Injektion zu vereinfachen, aber ich kann sicherlich von der ShellVM darauf zugreifen (die bereits als Singleton im Container registriert ist). –

1

Die Lösung, wie ich die Frage verstehe, ist relativ einfach - theDockControl von außen zur Verfügung stellen. Ich weiß, dass das mit automatisch generierten WinForms/WPF/was auch immer passiert - Sie benutzen Mist, aber ich fürchte, es gibt hier keine schönen Lösungen.

+0

Ich denke du hast den Punkt meiner Unruhe bekommen. Aus der Sicht des Designs ist die Bereitstellung der gleichen Steuerungsinstanz von außen sowohl für den Adapter als auch für das Fenster der richtige Weg - und es ist SO einfach !; es kann aus anderen Gründen peinlich sein, aber das ist ein anderes Problem. Ich denke, die verzögerte Registrierung ist unbestritten, obwohl ... Vielen Dank für Ihre Hilfe. –

+0

Keine Sorge. Du bekommst das Abzeichen das nächste Mal :) –

Verwandte Themen