.NET 的简单事件总线 [关闭]

Posted

技术标签:

【中文标题】.NET 的简单事件总线 [关闭]【英文标题】:A simple event bus for .NET [closed] 【发布时间】:2008-12-15 12:49:17 【问题描述】:

我想制作一个非常简单的事件总线,它允许任何客户端订阅特定类型的事件,并且当任何发布者使用 EventBus.PushEvent() 方法在总线上推送事件时,只有订阅该特定事件类型的客户端将得到该事件。

我正在使用 C# 和 .NET 2.0。

【问题讨论】:

基于redis的消息队列github.com/antirez/disque 【参考方案1】:

Tiny Messenger 是一个不错的选择,我已经在实际项目中使用它 2.5 年了。来自 Wiki 的一些代码示例(链接如下):

出版

messageHub.Publish(new MyMessage());

订阅

messageHub.Subscribe<MyMessage>((m) =>  MessageBox.Show("Message Received!"); );
messageHub.Subscribe<MyMessageAgain>((m) =>  MessageBox.Show("Message Received!"); , (m) => m.Content == "Testing");

代码在 GitHub 上:https://github.com/grumpydev/TinyMessenger

维基在这里:https://github.com/grumpydev/TinyMessenger/wiki

它还有一个 Nuget 包

Install-Package TinyMessenger

【讨论】:

+1 为 TinyMessenger,微型消息总线。【参考方案2】:

另一个,受 EventBus for android 的启发,但更简单:

public class EventBus

    public static EventBus Instance  get  return instance ?? (instance = new EventBus());  

    public void Register(object listener)
    
        if (!listeners.Any(l => l.Listener == listener))
            listeners.Add(new EventListenerWrapper(listener));
    

    public void Unregister(object listener)
    
        listeners.RemoveAll(l => l.Listener == listener);
    

    public void PostEvent(object e)
    
        listeners.Where(l => l.EventType == e.GetType()).ToList().ForEach(l => l.PostEvent(e));
    

    private static EventBus instance;

    private EventBus()  

    private List<EventListenerWrapper> listeners = new List<EventListenerWrapper>();

    private class EventListenerWrapper
    
        public object Listener  get; private set; 
        public Type EventType  get; private set; 

        private MethodBase method;

        public EventListenerWrapper(object listener)
        
            Listener = listener;

            Type type = listener.GetType();

            method = type.GetMethod("OnEvent");
            if (method == null)
                throw new ArgumentException("Class " + type.Name + " does not containt method OnEvent");

            ParameterInfo[] parameters = method.GetParameters();
            if (parameters.Length != 1)
                throw new ArgumentException("Method OnEvent of class " + type.Name + " have invalid number of parameters (should be one)");

            EventType = parameters[0].ParameterType;
        

        public void PostEvent(object e)
        
            method.Invoke(Listener, new[]  e );
        
          

用例:

public class OnProgressChangedEvent


    public int Progress  get; private set; 

    public OnProgressChangedEvent(int progress)
    
        Progress = progress;
    


public class SomeForm : Form

    // ...

    protected override void OnLoad(EventArgs e)
    
        base.OnLoad(e);
        EventBus.Instance.Register(this);
    

    public void OnEvent(OnProgressChangedEvent e)
    
        progressBar.Value = e.Progress;
    

    protected override void OnClosed(EventArgs e)
    
        base.OnClosed(e);
        EventBus.Instance.Unregister(this);
    


public class SomeWorkerSomewhere

    void OnDoWork()
    
        // ...

        EventBus.Instance.PostEvent(new OnProgressChangedEvent(progress));

        // ...
    

【讨论】:

【参考方案3】:

Composite Application Block 包含一个可能对您有用的事件代理。

【讨论】:

【参考方案4】:

您还可以查看 Unity 扩展: http://msdn.microsoft.com/en-us/library/cc440958.aspx

[Publishes("TimerTick")]
public event EventHandler Expired;
private void OnTick(Object sender, EventArgs e)

  timer.Stop();
  OnExpired(this);


[SubscribesTo("TimerTick")]
public void OnTimerExpired(Object sender, EventArgs e)

  EventHandler handlers = ChangeLight;
  if(handlers != null)
  
    handlers(this, EventArgs.Empty);
  
  currentLight = ( currentLight + 1 ) % 3;
  timer.Duration = lightTimes[currentLight];
  timer.Start();

还有更好的吗?

【讨论】:

【参考方案5】:

我找到了Generic Message Bus 。这是一个简单的类。

【讨论】:

【参考方案6】:

另一个很好的实现可以在:

http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/EventBus.cs

用例可在以下位置访问: /trunk/Squared/Util/UtilTests/Tests/EventTests.cs

此实现不需要外部库。

一个改进可能是能够订阅类型而不是字符串。

【讨论】:

【参考方案7】:

您应该查看Hibernating Rhinos 中的第 3 集,Ayende 的屏幕投射系列 - “实现事件代理”。

它展示了如何使用 Windsor 实现一个非常简单的事件代理来连接事物。源代码也包含在内。

提议的事件代理解决方案非常简单,但不需要太多时间来扩充解决方案以允许参数与事件一起传递。

【讨论】:

【参考方案8】:

我创造了这个:

https://github.com/RemiBou/RemiDDD/tree/master/RemiDDD.Framework/Cqrs

ninject 存在依赖关系。 你有一个消息处理器。如果你想观察一个事件,实现“IObserver”如果你想处理一个命令实现“ICommandHandleer”

【讨论】:

以上是关于.NET 的简单事件总线 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

MassTransit一个优秀的.NET消息(事件)总线框架

.Net Core对于RabbitMQ封装分布式事件总线

.Net Core对于RabbitMQ封装分布式事件总线

NET Core 事件总线,分布式事务解决方案:CAP

Shashlik.EventBus.NET 事件总线,分布式事务最终一致性简介

事件总线模式——实例讲解