【发布时间】:2020-06-04 18:25:24
【问题描述】:
已经相当确定,在 ctors 中为使用 SimpleInjector 解析的类型工作是不好的做法。尽管这通常会导致此类类型的某些延迟初始化,但一个特别有趣的案例是 Reactive Extensions 订阅。
以一个展示Replay(1)语义的可观察序列为例(如果我们考虑StartWith,实际上是BehaviorSubject),例如
private readonly IObservable<Value> _myObservable;
public MyType(IService service)
{
_myObservable = service.OtherObservable
.StartWith(service.Value)
.Select(x => SomeTransform())
.Replay(1)
.RefCount();
}
public IObservable<Value> MyObservable => _myObservable;
现在假设,SomeTransform 的计算量很大。从 SimpleInjector 的角度来看,上述做法是不好的做法。好的,所以我们需要在 SimpleInjector 完成后调用某种Initialize() 方法。但是我们的重播语义和我们的StartWith() 呢?我们的消费者在Subscribe 时期望一个值(现在假设这保证会在初始化后发生)!
我们如何在满足 SimpleInjector 要求的同时以一种很好的方式绕过这些限制?以下是要求摘要:
- 不要在 ctor 中做大量工作(即
SomeTransform)不应该运行 -
_myObservable应该是readonly -
MyObservable应该表现出Replay(1)语义 - 我们应该总是有一个初始值(因此
StartWith) - 我们不想将
Subscribe放在MyType中并缓存值(我们喜欢不变性)
我尝试创建一个额外的 observable,它以 false 开头,然后在初始化时设置为 true,然后将其与 _myObservable 合并,但无法使其正常工作。此外,它似乎不是最好的解决方案。本质上,我想做的只是延迟到Initialize() 完成。一定有某种我看不到的方法来做到这一点?
【问题讨论】:
-
SomeTransform();在构造函数期间不会被调用。当有人实际使用MyObservable属性时使用它。 -
我对 Reactive Extensions 不是很熟悉,但是
SomeTransform()实际上会在构造函数中被调用,还是只有在其他服务推送一个值时才会发生这种情况?
标签: c# system.reactive simple-injector