事件总线实现问题
本文关键字:问题 实现 总线 事件 | 更新日期: 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
除此之外,我不能给你更多的建议,因为我不太明白你在做什么。
编辑
看看这个问题的公认答案。它包含一个链接到几年前实现这个的人的博客文章。看来你不需要重新发明轮子了