所以我可能会对以下代码提出几个问题,可能是因为我使用的是Subject
并且我不确定是否可以使用。
这对我来说很难解释,我不知道为什么,也许我缺少术语。
我正在尝试做的是让 1 个类型可以注册多个可观察量,这样我就可以传递这个类型并将所有可观察量分组并从中公开一个可观察量。
所以我的第一个问题我有一种感觉,我没有以正确的方式思考问题,我想知道这是正确的还是有一种更"被动"的方式来做这件事?
我的意思是,我有这个类型,你可以注册可观察量,而且这个相同的类型将公开我也可以订阅的单个可观察量。
我将尝试用下面的代码示例来解释一下。 因此,SomeTypeWithObservable
可能是将公开IObservable<SomeEvents>
的众多类型之一ReactiveTesting
类型是尝试将所有可观察量组合在一起并公开单个IObservable<SomEvents>
的类型。有一种RegisterObservable
方法可以将其发送到内部Subject<IObservable<SomeEvents>>
。构造函数将我想要公开的可观察设置为此主题的SelectMany
。
使用以下实现,在ReactiveTesting
构造函数中,我执行了一个SelectMany.Publish.RefCount
,然后使用虚拟订阅来启动可观察量,我注意到如果我不使用虚拟订阅,则不使用可观察量的注册。
所以我的第二个问题是代码可以有一个虚拟订阅来开始可观察量,或者我应该做我在评论下面所做的,我刚刚从 Publish 连接了一个可连接对象,然后立即连接它,或者他们都是错误的,在这种情况下,有人可以指出我正确的方向吗?
我的第三个问题我应该使用一个主题吗?
如果我在订阅之前调用RegisterObservable
,并且如果我没有放入虚拟Subscribe
或Connect
,那么我将不会观察触发的任何事件。
我的第四个问题有人可以解释后者吗? 我有点想,因为它是Publish
和RefCount
那么在有一个从可观察的订阅开始之前,没有什么可做的。
代码
--已编辑- 显示有多个可观察量我想在ReactiveTesting
中注册
enum SomeEvents
{
event1,
event2,
event3,
event4
}
interface ISomeTypeWithObservable
{
IObservable<SomeEvents> SomeObservableEvents { get; }
}
class SomeTypeWithObservable2 : ISomeTypeWithObservable
{
private event EventHandler SpecialEvent;
public SomeTypeWithObservable2()
{
var observableFromSpecialEvent = Observable.FromEventPattern(h => SpecialEvent += h, h => SpecialEvent -= h).Select(x => SomeEvents.event2);
SomeObservableEvents = Observable.Create<SomeEvents>(observer =>
{
return observableFromSpecialEvent.Subscribe(observer);
})
.Publish()
.RefCount();
}
public IObservable<SomeEvents> SomeObservableEvents { get; }
public void TriggerEvent()
{
SpecialEvent.Invoke(this, new EventArgs());
}
}
class SomeTypeWithObservable : ISomeTypeWithObservable
{
private event EventHandler SpecialEvent;
public SomeTypeWithObservable()
{
var observableFromSpecialEvent = Observable.FromEventPattern(h => SpecialEvent += h, h => SpecialEvent -= h).Select(x => SomeEvents.event1);
SomeObservableEvents = Observable.Create<SomeEvents>(observer =>
{
return observableFromSpecialEvent.Subscribe(observer);
})
.Publish()
.RefCount();
}
//Some code in here that will produce things to observe, maybe Observable.FromEventPattern...
public IObservable<SomeEvents> SomeObservableEvents { get; }
public void TriggerEvent()
{
SpecialEvent.Invoke(this, new EventArgs());
}
}
class ReactiveTesting
{
private Subject<IObservable<SomeEvents>> _innerEvents = new Subject<IObservable<SomeEvents>>();
public IObservable<SomeEvents> AllEvents;
public ReactiveTesting()
{
AllEvents = _innerEvents.SelectMany(x => x).Publish().RefCount();
AllEvents.Subscribe(next => { }, exception => { }, () => { });
//This instead of the above??
//var connectableObservable = _innerEvents.SelectMany(x => x).Publish();
//AllEvents = connectableObservable;
//connectableObservable.Connect();
}
public void RegisterObservable(ISomeTypeWithObservable someTypeWithObservable)
{
_innerEvents.OnNext(someTypeWithObservable.SomeObservableEvents);
}
}
class Program
{
static void Main(string[] args)
{
var reactiveTesting = new ReactiveTesting();
var someTypeWithObservable = new SomeTypeWithObservable();
var someTypeWithObservable2 = new SomeTypeWithObservable2();
reactiveTesting.AllEvents.Subscribe(next => Console.WriteLine(string.Format("Subscriber 1 - {0}", next.ToString("G"))));
reactiveTesting.AllEvents.Subscribe(next => Console.WriteLine(string.Format("Subscriber 2 - {0}", next.ToString("G"))));
reactiveTesting.RegisterObservable(someTypeWithObservable);
reactiveTesting.RegisterObservable(someTypeWithObservable2);
someTypeWithObservable.TriggerEvent();
someTypeWithObservable.TriggerEvent();
someTypeWithObservable.TriggerEvent();
someTypeWithObservable2.TriggerEvent();
someTypeWithObservable2.TriggerEvent();
someTypeWithObservable2.TriggerEvent();
Console.WriteLine("Press key...");
Console.ReadLine();
}
}
所以我的第一个问题我有一种感觉,我没有在考虑事情 正确的方式,我想知道这是正确的还是还有更多 "反应性"方式?
在ReactiveTesting
中使用Subject
通常是一种提示,表明您有一些命令式代码可以消除或进一步推送。它可能需要重写一些周围的代码。在这种情况下,您最终会得到如下所示的内容:
class ReactiveTesting
{
public IObservable<SomeEvents> AllEvents { get; }
public ReactiveTesting(IObservable<IObservable<SomeEvents>> eventSource)
{
AllEvents = eventSource.Merge().Publish().RefCount();
}
}
class Program
{
public static void Main(string[] args)
{
var someTypeWithObservable = new SomeTypeWithObservable();
var reactiveTesting = new ReactiveTesting(Observable.Return(someTypeWithObservable.SomeObservableEvents));
reactiveTesting.AllEvents.Subscribe(next => Console.WriteLine(string.Format("Subscriber 1 - {0}", next.ToString("G"))));
reactiveTesting.AllEvents.Subscribe(next => Console.WriteLine(string.Format("Subscriber 2 - {0}", next.ToString("G"))));
someTypeWithObservable.TriggerEvent();
someTypeWithObservable.TriggerEvent();
someTypeWithObservable.TriggerEvent();
Console.WriteLine("Press key...");
Console.ReadLine();
}
}
所以我的第二个问题是代码可以有一个虚拟订阅 从可观察的开始,或者我应该做我在下面做的事情 评论我刚刚从发布连接然后连接 紧接着,或者他们都错了,在这种情况下,可以 有人为我指出正确的方向?
这应该没有必要。它对我的作用与删除它相同。虚拟订阅有助于.Replay().Refcount()
。我不明白.Publish()
的意义.
我的第三个问题 我应该使用一个主题吗?
它们基本上是一种代码气味。如果你能消除它们,或者把它们从你的业务逻辑中推开,你会更好。