Вопрос

Я хочу создать очень простую шину событий, которая позволит любому клиенту подписаться на событие определенного типа и когда любой издатель отправляет событие на шину, используя EventBus.PushEvent() только те клиенты, которые подписались на этот конкретный тип события, получат это событие.

Я использую С# и .NET 2.0.

Это было полезно?

Решение 4

я нашел Общая шина сообщений .Это один простой класс.

Другие советы

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

Еще один, вдохновленный EventBus для 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));

        // ...
    }
}

Вы также можете проверить расширения 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();
}

Есть ли лучшие?

А Составной прикладной блок включает в себя брокер событий, который может вам пригодиться.

Еще одну хорошую реализацию можно найти по адресу:

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

Варианты использования доступны по адресу:/trunk/Squared/Util/UtilTests/Tests/EventTests.cs

Эта реализация не требует внешней библиотеки.

Улучшением может стать возможность подписки по типу, а не по строке.

Вам стоит посмотреть 3 серию Спящие носороги, серия скринкастов Айенде - "Реализация брокера событий".

Он показывает, как можно реализовать очень простой брокер событий, используя Windsor для подключения.Исходный код также включен.

Предлагаемое решение брокера событий очень простое, но его расширение, позволяющее передавать аргументы вместе с событиями, не займет много часов.

Я создал это:

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

Есть зависимость от ninject.У вас есть процессор сообщений.Если вы хотите наблюдать за событием, реализуйте «IObserver», если вы хотите обрабатывать команду, реализуйте «ICommandHandleer».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top