如何将Reactive Extensions用于事件总线

时间:2016-03-17 17:25:37

标签: c# linq system.reactive

我很难弄清楚如何使用反应式扩展在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 ??
     }
 }

2 个答案:

答案 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> eventBusstatic,但课程没有。我不知道这是否有意。此外,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