我很难弄清楚如何使用反应式扩展在C#中创建事件总线,而不推荐我理解的Subject类。
大多数IEvent都是我自己的,但有些像鼠标和放大器。键盘事件将由WPF提供。
我更喜欢将事件发布到事件总线而不是使用Observable.FromEventPattern的事件处理程序,因为其中一些事件有时只会被订阅者记录而不会被执行。
下面是一段代码,展示了我要做的事情。
public interface IEvent { } // marker interface
public class BarcodeReaderEvent : EventArgs, IEvent
{ }
public class MouseEvent : EventArgs, IEvent
{ }
public class MyEventBus
{
private static IObservable<IEvent> eventBus = ??
public void Post<IEvent>(IEvent theEvent)
{
// What goes here?
}
public IDisposable Subscribe()
{
return ??
}
}
答案 0 :(得分:3)
主题的使用仅作为使用事件总线的推荐。如果你决定让每个人都发表和听取一个观点,那么也可以全力以赴并使用一个主题。
正如其他帖子所建议的那样,标准建议是使用专门的资源/服务来公开特定于域的事件。而不是拥有一般的事件总线/事件聚合器(反模式IMO),其中每个客户端必须过滤掉他们希望发布的消息。他们应该只订阅专用端点。
答案 1 :(得分:2)
如果您想要使用您提出的结构,则需要使用主题。
您的代码基本上如下所示:
public interface IEvent { }
public class BarcodeReaderEvent : EventArgs, IEvent { }
public class MouseEvent : EventArgs, IEvent { }
public class MyEventBus
{
private Subject<IEvent> _subject = new Subject<IEvent>();
private IObservable<IEvent> _eventBus;
public MyEventBus()
{
_eventBus = _subject.AsObservable();
}
public void Post(IEvent theEvent)
{
_subject.OnNext(theEvent);
}
public IDisposable Subscribe(IObserver<IEvent> observer)
{
return _eventBus.Subscribe(observer);
}
}
然而,主题的问题是,如果主题出现错误,那么每个主题订阅都会收到OnError
通知,然后所有订阅都将结束。
你的代码确实也有一些“怪异”。您的private static IObservable<IEvent> eventBus
是static
,但课程没有。我不知道这是否有意。此外,public void Post<IEvent>(IEvent theEvent)
似乎意味着您希望将IEvent
作为泛型类型传递(意味着您正在使用泛型类型隐藏实际的接口类型)。你可能意味着public void Post<T>(T theEvent) where T : IEvent
,但我无法分辨。
你可以试试这个,我觉得它更接近你真正想要的东西,看看它是否更适合你:
public class MyEventBus
{
private Subject<IEvent> _subject = new Subject<IEvent>();
public void Post<T>(T message) where T : IEvent
{
_subject.OnNext(message);
}
public IObservable<T> AsObservable<T>() where T : IEvent
{
return _subject.OfType<T>();
}
}
或者,您可能希望使用Rx查看此更复杂事件总线的示例:https://github.com/reactiveui/ReactiveUI/blob/master/ReactiveUI/MessageBus.cs