DryIOC 在 Facade 之间共享单例
DryIOC Sharing Singletons between Facades
我正在开发一个系统,该系统在几个不同的时间范围内处理各种金融工具的金融数据。
例如:
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)
每个时间帧都有一个相当复杂的处理管道,我使用 DryIOC 通过管道路由数据,使用此处所述的 EventAggregator:
DryIOC 非常适合这个,因为它速度超快,可以跟上我需要的 data/events 数量。
我有工具级别的依赖项,需要在该工具的不同时间范围之间共享。
而且我还有全局依赖项,例如需要在所有工具和所有时间范围之间共享的经纪商连接管理器。
容器是在运行时创建的;我可能会切换 on/off 不同的工具和时间范围,并且需要制作一个新容器。
Facade 似乎很适合这个。我可以从一个全局容器开始,对于任何被激活的仪器,为该仪器制作一个门面。然后从那个容器中为每个时间范围制作一个容器。 Facade 容器中的解析使用在那里定义的本地注册,然后在未解析时回退到 parent。
但是,如文档中所述,Facade 有自己的单例。当我尝试将 Facade 的全局依赖项作为单例解析时,我得到了一个新实例。
此测试失败:
[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);
}
我花了三天时间与 Facades、Scopes、NamedScopes 以及所有这些东西的组合作斗争。范围不起作用,因为如果我为工具创建一个新范围,然后为工具内的每个时间范围创建一个新范围并使用当前范围解决 - 我仍然得到一个新版本,因为每个时间范围都在其自己的范围内。
命名范围不起作用,因为我只知道运行时的工具名称,并为新工具添加新注册,时间框架发生冲突。
我怎样才能让子容器分开,然后与他们的 parent 共享单例?
更新:
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);
}
产生以下异常:
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"
附带说明一下,您无法从 visual studio 测试运行器复制异常。
我最终通过使用 WithRegistrationsCopy()
实现了这一点
例如
_localContainer = container.WithRegistrationsCopy();
这使我能够在子容器中获得顶级单例实例,但在其他容器不知道的子容器中也有特定的注册。
我正在开发一个系统,该系统在几个不同的时间范围内处理各种金融工具的金融数据。
例如:
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)
每个时间帧都有一个相当复杂的处理管道,我使用 DryIOC 通过管道路由数据,使用此处所述的 EventAggregator:
DryIOC 非常适合这个,因为它速度超快,可以跟上我需要的 data/events 数量。
我有工具级别的依赖项,需要在该工具的不同时间范围之间共享。
而且我还有全局依赖项,例如需要在所有工具和所有时间范围之间共享的经纪商连接管理器。
容器是在运行时创建的;我可能会切换 on/off 不同的工具和时间范围,并且需要制作一个新容器。
Facade 似乎很适合这个。我可以从一个全局容器开始,对于任何被激活的仪器,为该仪器制作一个门面。然后从那个容器中为每个时间范围制作一个容器。 Facade 容器中的解析使用在那里定义的本地注册,然后在未解析时回退到 parent。
但是,如文档中所述,Facade 有自己的单例。当我尝试将 Facade 的全局依赖项作为单例解析时,我得到了一个新实例。
此测试失败:
[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);
}
我花了三天时间与 Facades、Scopes、NamedScopes 以及所有这些东西的组合作斗争。范围不起作用,因为如果我为工具创建一个新范围,然后为工具内的每个时间范围创建一个新范围并使用当前范围解决 - 我仍然得到一个新版本,因为每个时间范围都在其自己的范围内。
命名范围不起作用,因为我只知道运行时的工具名称,并为新工具添加新注册,时间框架发生冲突。
我怎样才能让子容器分开,然后与他们的 parent 共享单例?
更新:
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);
}
产生以下异常:
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"
附带说明一下,您无法从 visual studio 测试运行器复制异常。
我最终通过使用 WithRegistrationsCopy()
实现了这一点例如
_localContainer = container.WithRegistrationsCopy();
这使我能够在子容器中获得顶级单例实例,但在其他容器不知道的子容器中也有特定的注册。