2016-11-09 1 views
1

Ich arbeite an einem System, das Finanzdaten für verschiedene Finanzinstrumente in verschiedenen Zeitrahmen verarbeitet.DryIOC Sharing Singletons zwischen Fassaden

Zum Beispiel:

EUR/USD 
    - m1 Timeframe (1 Minute) 
    - m5 Timeframe (5 Minute) 
    - m15 Timeframe (15 Minute) 
GBP/USD 
    - m1 Timeframe (1 Minute) 
    - m5 Timeframe (5 Minute) 
    - m15 Timeframe (15 Minute) 

Der zeitliche Rahmen, haben jeweils eine ziemlich komplexe Verarbeitungspipeline, und ich bin mit DryIOC, um Daten durch die Pipeline, ein Eventaggregator mit wie hier beschrieben: DryIOC Event Aggregator

DryIOC ist perfekt dafür, weil es super schnell ist und mit der Menge an Daten/Ereignissen mithalten kann, die ich brauche.

Ich habe Abhängigkeiten, die auf der Instrumentenebene sind, die zwischen den verschiedenen Zeitrahmen dieses Instruments geteilt werden müssen.

Und ich habe auch globale Abhängigkeiten wie ein Broker Verbindungsmanager, die zwischen allen Instrumenten und Zeitrahmen geteilt werden müssen.

Container werden zur Laufzeit erstellt; Ich kann verschiedene Instrumente und Zeitrahmen ein- und ausschalten und muss einen neuen Container erstellen.

Fassade scheint perfekt dafür. Ich kann mit einem globalen Container beginnen und für jedes Instrument, das aktiviert wird, eine Fassade für das Instrument erstellen. Und aus diesem Container einen Container für jeden Zeitrahmen erstellen. Auflösungen im Container "Fassade" verwenden die dort definierten lokalen Registrierungen und greifen dann auf den übergeordneten Zweig zurück, wenn sie nicht aufgelöst werden.

Wie jedoch in der Dokumentation beschrieben Fassaden haben ihre eigenen Singletons. Und wenn ich versuche, eine globale Abhängigkeit von einer Fassade als Singleton zu lösen, bekomme ich eine neue Instanz.

Dieser Test schlägt fehl:

[Test] 
public void Test() 
{ 
    var globalContainer = new Container(); 

    globalContainer.Register<IGlobalDependency, GlobalDependency>(Reuse.Singleton); 

    var EURUSD_Container = new Container(rules => rules.WithFallbackContainer(globalContainer)); 

    EURUSD_Container.Register<IInstrumentDependency, InstrumentDependency>(Reuse.Singleton); 

    var EURUSD_Timeframe_1_Container = EURUSD_Container.CreateFacade(); 

    EURUSD_Timeframe_1_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.Singleton); 

    var EURUSD_Timeframe_2_Container = EURUSD_Container.CreateFacade(); 
    EURUSD_Timeframe_2_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.Singleton); 


    var globalfromTimeframe1 = EURUSD_Timeframe_1_Container.Resolve<IGlobalDependency>(); 
    var globalfromTimeframe2 = EURUSD_Timeframe_2_Container.Resolve<IGlobalDependency>(); 

    Assert.AreSame(globalfromTimeframe1, globalfromTimeframe2); 
} 

Ich habe 3 Tage verbrachte mit Fassaden kämpfen, Scopes, NamedScopes und Kombinationen von all diesen Dingen. Scopes funktionieren nicht, da wenn ich einen neuen Bereich für ein Instrument und dann einen neuen Bereich für jeden Zeitrahmen innerhalb des Instruments mache und mit dem InCurrent-Bereich auflöst - bekomme ich immer noch eine neue Version, weil jeder Zeitrahmen in seinem eigenen Umfang ist.

Benannte Bereiche funktionierten nicht, da ich nur die Gerätenamen zur Laufzeit kenne und neue Registrierungen für neue Instrumente hinzufüge, Zeitrahmen kollidierten.

Wie kann ich Subcontainer getrennt halten, aber dann Singletons mit ihren Eltern teilen?

Update:

public void ScopeTest() 
{ 
    var globalContainer = new Container(); 

    globalContainer.Register<IGlobalDependency, GlobalDependency>(Reuse.Singleton); 

    var EURUSD_Container = globalContainer.OpenScope("EUR/USD"); 

    EURUSD_Container.Register<IInstrumentDependency, InstrumentDependency>(Reuse.InCurrentNamedScope("EUR/USD"), serviceKey: "EUR/USD"); 

    var EURUSD_Timeframe_1_Container = EURUSD_Container.OpenScope("m1"); 

    EURUSD_Timeframe_1_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.InCurrentNamedScope("m1"), serviceKey: "m1"); 

    var EURUSD_Timeframe_2_Container = EURUSD_Timeframe_1_Container.OpenScope("m5"); 

    EURUSD_Timeframe_2_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.InCurrentNamedScope("m5"), serviceKey:"m5"); 

    var USDJPY_Container = globalContainer.OpenScope("USD/JPY"); 

    EURUSD_Container.Register<IInstrumentDependency, InstrumentDependency>(Reuse.InCurrentNamedScope("USD/JPY"), serviceKey: "USD/JPY"); 

    var USDJPY_Timeframe_1_Container = USDJPY_Container.OpenScope("m1"); 

    USDJPY_Timeframe_1_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.InCurrentNamedScope("m1"), serviceKey:"m1"); 

    var USDJPY_Timeframe_2_Container = USDJPY_Container.OpenScope("m5"); 

    USDJPY_Timeframe_2_Container.Register<ITimeframeDependency, TimeframeDependency>(Reuse.InCurrentNamedScope("m5"), serviceKey:"m5"); 

    var globalfromEURUSDTimeframe1 = EURUSD_Timeframe_1_Container.Resolve<IGlobalDependency>(); 
    var globalfromEURUSDTimeframe2 = EURUSD_Timeframe_2_Container.Resolve<IGlobalDependency>(); 

    var globalfromUSDJPYTimeframe1 = EURUSD_Timeframe_1_Container.Resolve<IGlobalDependency>(); 
    var globalfromUSDJPYTimeframe2 = EURUSD_Timeframe_2_Container.Resolve<IGlobalDependency>(); 

    Assert.AreSame(globalfromEURUSDTimeframe1, globalfromEURUSDTimeframe2); 
    Assert.AreSame(globalfromUSDJPYTimeframe1, globalfromUSDJPYTimeframe2); 
    Assert.AreSame(globalfromEURUSDTimeframe1, globalfromUSDJPYTimeframe2); 
} 

Erzeugt die folgende Ausnahme:

DryIoc.ContainerException: Unable to register service Namespace.ITimeframeDependency - {DI=25, ImplType="Namespace.TimeframeDependency", Reuse=CurrentScopeReuse {Name="m1", Lifespan=100}} with duplicate key [m1]. Already registered service with same key is {ID=22.... etc.... Name="m1" 

auf einer Seite merken Sie sich dessen so ärgerlich Sie können keine Ausnahmen von dem Visual Studio Test Runner kopieren.

+0

Ich gehe davon aus, dass Sie Ihre Fassaden anschließend entsorgen? Was soll dann mit geteilten Singletons passieren? – dadhi

+0

Können Sie mehr erläutern, warum benannte Bereiche nicht für Sie arbeiten, vielleicht über ein kleines Beispiel? – dadhi

+0

aktualisiert die Frage mit einem Beispiel – reach4thelasers

Antwort

2

I gelang dies am Ende unter Verwendung von WithRegistrationsCopy()

z.B. zu erreichen

_localContainer = container.WithRegistrationsCopy(); 

Dies ermöglicht es mir Top-Level-Singleton-Instanzen in subcontainers zu bekommen, aber auch spezifische Eintragungen in subcontainers nicht auf andere Behälter bekannt.

+0

Froh, dass es für dich funktioniert hat. Ich interessiere mich für reale Fälle der Verwendung von Fassaden-/Kindercontainern, um Dinge in V3 zu verbessern: https://bitbucket.org/dadhi/dryioc/issues/270/diagnose-fallback-facade-container – dadhi