23

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

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

4

8 回答 8

26

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");

The code's on GitHub: https://github.com/grumpydev/TinyMessenger

The Wiki is here: https://github.com/grumpydev/TinyMessenger/wiki

It has a Nuget package also

Install-Package TinyMessenger
于 2011-12-19T10:54:29.897 回答
9

Another one, inspired by EventBus for android, but far simpler:

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 });
        }
    }      
}

Use case:

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));

        // ...
    }
}
于 2014-05-06T08:00:17.867 回答
2

复合应用程序块包括一个可能对您有用的事件代理。

于 2008-12-15T13:25:48.453 回答
2

我找到了通用消息总线。这是一门简单的课。

于 2008-12-15T15:05:45.443 回答
2

您还可以查看 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();
}

有更好的吗?

于 2009-11-05T14:56:27.750 回答
1

另一个很好的实现可以在以下位置找到:

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

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

此实现不需要外部库。

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

于 2010-04-22T14:51:20.897 回答
0

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

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

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

于 2008-12-15T13:20:39.790 回答
0

I created this :

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

There is a dependancy with ninject. You got a MessageProcessor. If you want to obsere an event, implement "IObserver" if you want to handle a command implement "ICommandHandleer"

于 2013-02-25T12:30:14.937 回答