事件总线实现问题

本文关键字:问题 实现 总线 事件 | 更新日期: 2023-09-27 18:01:42

我正在尝试实现简单的事件总线

我是这样开始的:

public class RegistrationData
{
    public object RegisteredObject { get; set; }
    public Type eventType { get; set; }
    public EventHandler MethodToInvoke;
}
public class EventBus
{
    private static EventBus instance;
    private static readonly object lockObject = new object();
    private static List<RegistrationData> registrationList;
    private EventBus()
    {
    }
    public static EventBus Instance
    {
        get
        {
            lock (lockObject)
            {
                registrationList = new List<RegistrationData>();
                return instance ?? new EventBus();
            }
        }
    }
    public void Subscribe(RegistrationData registrationData)
    {
        if(!registrationList.Contains(registrationData)) registrationList.Add(registrationData);
    }
    public void Unsubscribe(object objectToUnregister, Type eventType)
    {
        foreach(RegistrationData data in registrationList)
            if (data.RegisteredObject == objectToUnregister && data.eventType == eventType) registrationList.Remove(data);
    }
    public void UnregisterAllMessages(object objectToUnregister)
    {
        foreach(RegistrationData data in registrationList)
            if(data.RegisteredObject == objectToUnregister) registrationList.Remove(data);
    }
    public void PublishEvent(object sender, EventArgs eventArgs)
    {
        foreach (RegistrationData data in registrationList)
            if (EventArgs is typeof(data.Type)) data.MethodToInvoke(sender, eventArgs);
    }
}

但是我在publishhevent方法中有问题。我无法确定事件参数的类型。我怀疑这一切都是错误的。

有人能指出我做错了什么,我应该如何实现这个?或者事件总线一般是如何实现的,或者我可以使用一些框架,而不是自己实现并花费时间在上面。

事件总线实现问题

嗯,不太确定你的Eventbus应该如何表现。如果你不知道你要去哪里,那么看看其他人是如何实现这个问题的会很有用。

  • 在校准中有一个接地气的事件聚合器。微项目
  • 当我需要一个事件聚合器时,我喜欢使用MemBus,部分原因是我自己写的,部分原因是它涵盖了我在这方面的所有需求。它比caliburn的更复杂,但它有更多的功能

我认为您应该从定义事件总线开始。你认为事件总线和内建的。net触发和接收事件的机制有什么不同?到目前为止,看起来它实现的只不过是。net事件,. net本质上支持事件处理,所以如果你只需要。net已经提供的,你就不需要事件总线了:

class Program
{
  static void Main(string[] args)
  {
     BusinessObject1 bo = new BusinessObject1("First Value");
     // Subscribe
     bo.Publish += new BusinessObject.PublishObject(bo_Publish);
     bo.Update("Second Value");
     // UnSubscribe
     bo.Publish -= new BusinessObject.PublishObject(bo_Publish);
     bo.Update("Third Value");
     // Subscribe multiple
     bo.Publish += new BusinessObject.PublishObject(bo_Publish);
     bo.Publish += new BusinessObject.PublishObject(bo_Publish2);
     bo.Update("Fourth Value");
     // UnregisterAllMessages
     bo.UnsubcribeAll();
     bo.Update("Fifth Value");
  }
  static void bo_Publish(BusinessObject sender, EventArgs args)
  {
     if (sender is BusinessObject1)
     {
        BusinessObject1 bo1 = (BusinessObject1)sender;
        BusinessObject1.PublishBusinessObject1EventArgs args1 =
           (BusinessObject1.PublishBusinessObject1EventArgs)args;
        Console.WriteLine("Updated {0} to {1}", args1.oldValue, bo1.Value);
     }
  }
  static void bo_Publish2(BusinessObject sender, EventArgs args)
  {
     if (sender is BusinessObject1)
     {
        BusinessObject1 bo1 = (BusinessObject1)sender;
        BusinessObject1.PublishBusinessObject1EventArgs args1 =
           (BusinessObject1.PublishBusinessObject1EventArgs)args;
        Console.WriteLine("Second handler detected updated of {0} to {1}", args1.oldValue, bo1.Value);
     }
  }
}
abstract class BusinessObject
{
  public delegate void PublishObject(BusinessObject sender, EventArgs args);
  public event PublishObject Publish;
  // PublishEvent
  protected void Update(EventArgs args)
  {
     if (Publish != null)
        Publish(this, args);
  }
  public void UnsubcribeAll()
  {
     Publish = null;
  }
}
class BusinessObject1 : BusinessObject
{
  public class PublishBusinessObject1EventArgs : EventArgs
  {
     public string oldValue;
     public PublishBusinessObject1EventArgs(string oldValue)
     {
        this.oldValue = oldValue;
     }
  }
  public delegate void PublishBusinessObject1(BusinessObject1 sender, PublishBusinessObject1EventArgs args);
  public string Value {get; private set;}
  public BusinessObject1(string value)
  {
     this.Value = value;
  }
  public void Update(string newValue)
  {
     PublishBusinessObject1EventArgs args = new PublishBusinessObject1EventArgs(Value);
     Value = newValue;
     base.Update(args);
  }
}
编辑:

如果你不希望你的业务对象不得不从一个共同的基类继承(正如你在评论中建议的),你可以做一些修改,使EventBus站得更独立,但你仍然不需要重新实现所有的事件注册框架来做到这一点:

class Program
{
  static void Main(string[] args)
  {
     BusinessObject1 bo = new BusinessObject1("First Value");
     // Subscribe
     EventBus.Publish += new EventBus.PublishObject(EventBus_Publish);
     bo.Update("Second Value");
     // UnSubscribe
     EventBus.Publish -= new EventBus.PublishObject(EventBus_Publish);
     bo.Update("Third Value");
     // Subscribe multiple
     EventBus.Publish += new EventBus.PublishObject(EventBus_Publish);
     EventBus.Publish += new EventBus.PublishObject(EventBus_Publish2);
     bo.Update("Fourth Value");
     // UnregisterAllMessages
     EventBus.UnsubcribeAll();
     bo.Update("Fifth Value");
  }
  static void EventBus_Publish(object sender, EventArgs args)
  {
     if (sender is BusinessObject1)
     {
        BusinessObject1 bo1 = (BusinessObject1)sender;
        BusinessObject1.PublishBusinessObject1EventArgs args1 =
           (BusinessObject1.PublishBusinessObject1EventArgs)args;
        Console.WriteLine("Updated {0} to {1}", args1.oldValue, bo1.Value);
     }
  }
  static void EventBus_Publish2(object sender, EventArgs args)
  {
     if (sender is BusinessObject1)
     {
        BusinessObject1 bo1 = (BusinessObject1)sender;
        BusinessObject1.PublishBusinessObject1EventArgs args1 =
           (BusinessObject1.PublishBusinessObject1EventArgs)args;
        Console.WriteLine("Second handler detected updated of {0} to {1}", args1.oldValue, bo1.Value);
     }
  }
}
static class EventBus
{
  public delegate void PublishObject(object sender, EventArgs args);
  public static event PublishObject Publish;
  // PublishEvent
  public static void Update(object sender, EventArgs args)
  {
     if (Publish != null)
        Publish(sender, args);
  }
  public static void UnsubcribeAll()
  {
     Publish = null;
  }
}
class BusinessObject1
{
  public class PublishBusinessObject1EventArgs : EventArgs
  {
     public string oldValue;
     public PublishBusinessObject1EventArgs(string oldValue)
     {
        this.oldValue = oldValue;
     }
  }
  public delegate void PublishBusinessObject1(BusinessObject1 sender, PublishBusinessObject1EventArgs args);
  public string Value { get; private set; }
  public BusinessObject1(string value)
  {
     this.Value = value;
  }
  public void Update(string newValue)
  {
     PublishBusinessObject1EventArgs args = new PublishBusinessObject1EventArgs(Value);
     Value = newValue;
     EventBus.Update(this, args);
  }
}

编辑2:顺便说一下,如果您希望对订阅过程有更多的控制,您也可以通过定义自定义事件访问器来获得更多的控制,如http://msdn.microsoft.com/en-us/library/bb882534.aspx:

所述
static class EventBus
{
  public delegate void PublishObject(object sender, EventArgs args);
  private static List<PublishObject> subscribers = new List<PublishObject>();
  public static event PublishObject Publish
  {
     add
     {
        subscribers.Add(value);
        Console.WriteLine("Added subscriber {0}.{1}", value.Method.DeclaringType.Name, value.Method.Name);
     }
     remove
     {
        bool result = subscribers.Remove(value);
        Console.WriteLine("Removed subscriber {0}.{1} ({2})", value.Method.DeclaringType.Name, value.Method.Name, result ? "success" : "failure");
     }
  }
  // PublishEvent
  public static void Update(object sender, EventArgs args)
  {
     foreach (PublishObject p in subscribers)
     {
        Console.WriteLine("Publishing to {0}.{1}", p.Method.DeclaringType.Name, p.Method.Name);
        p.Invoke(sender, args);
     }
  }
  public static void UnsubcribeAll()
  {
     subscribers.Clear();
  }
}

好吧,作为第一个建议,在我看来,好像您试图将其实现为单例。否则

private static EventBus instance;

对什么有好处?但是私有实例成员永远不会被分配到任何地方,这是我建议你应该修复的一件事。作为参考,这里有一篇关于各种单例实现的好文章。如果您可以访问。net,我建议您使用LazySingleton3方法。

想到的唯一一件事是,这看起来可能是泛型的用例。看一看EventHandler<TEventArgs> Delegate

除此之外,我不能给你更多的建议,因为我不太明白你在做什么。

编辑

看看这个问题的公认答案。它包含一个链接到几年前实现这个的人的博客文章。看来你不需要重新发明轮子了