C#中委托、事件的好处,只需在某个类中提前定义好公开的委托或事件(委托的特殊表现形式)变量,然后在其它类中就可以很随意的订阅该委托或事件,当委托或事件被触发执行时,会自动通知所有的订阅者进行消费处理。(观察者模式用委托来实现是最好不过了,DDD所提倡的事件驱动其根本理念也是如此),当然我这里想到的是不需要在每个类中进行定义委托或事件,而是由一个统一的中介者(即EventPublishSubscribeUtils)来提供事件的订阅及发布操作,这样各模块之间无需直接依赖,只需通过中介者完成发布通知与订阅回调即可?
1.定义一个事件发布订阅帮助类,EventPublishSubscribeUtils
/// <summary>
/// 自定义事件发布订阅回调工具类(业务解藕、关注点分离,避免互相依赖)
/// 观察者模式
/// </summary>
public static class EventPublishSubscribeUtils
{
private static ConcurrentDictionary<Type, EventHandler<object>> EventHandlers { get; } = new ConcurrentDictionary<Type, EventHandler<object>>();
private static void removeRegisters(ref EventHandler<object> srcEvents, EventHandler<object> removeTargetEvents)
{
var evtTypes = removeTargetEvents.GetInvocationList().Select(d => d.GetType());
var registeredEventHandlers = Delegate.Combine(srcEvents.GetInvocationList().Where(ei => evtTypes.Contains(ei.GetType())).ToArray());
srcEvents -= (EventHandler<object>)registeredEventHandlers;
}
public static void Register<T>(EventHandler<object> eventHandlers)
{
EventHandlers.AddOrUpdate(typeof(T), eventHandlers,
(t, e) =>
{
//先根据订阅委托类型匹匹配过滤掉之前已有的相同订阅,然后再重新订阅,防止重复订阅,多次执行的情况。
removeRegisters(ref e, eventHandlers);
e += eventHandlers;
return e;
});
}
public static void UnRegister<T>(EventHandler<object> eventHandlers = null)
{
Type eventMsgType = typeof(T);
if (eventHandlers == null)
{
EventHandlers.TryRemove(eventMsgType, out eventHandlers);
return;
}
var e = EventHandlers[eventMsgType];
removeRegisters(ref e, eventHandlers);
}
public static void PublishEvent<T>(T eventMsg, object sender)
{
Type eventMsgType = eventMsg.GetType();
if (EventHandlers.ContainsKey(eventMsgType))
{
EventHandlers[eventMsgType].Invoke(sender, eventMsg);
}
}
}
2.使用通过EventPublishSubscribeUtils.Register注册订阅事件消息,通过EventPublishSubscribeUtils.PublishEvent发布事件通知
class EventMessage
{
public string Name { get; set; }
public string Msg { get; set; }
public DateTime CreatedDate { get; set; }
}
class DemoA
{
public DemoA()
{
EventHandler<object> eventHandlers = EventCallback1;
eventHandlers += EventCallback2;
EventPublishSubscribeUtils.Register<EventMessage>(eventHandlers);
}
private void EventCallback1(object sender, object e)
{
string json = JsonConvert.SerializeObject(e);
System.Diagnostics.Debug.WriteLine($"EventCallback1=> sender:{sender},e:{json}");
}
private void EventCallback2(object sender, object e)
{
string json = JsonConvert.SerializeObject(e);
System.Diagnostics.Debug.WriteLine($"EventCallback2=> sender:{sender},e:{json}");
}
}
class DemoB
{
public void ShowMsg(string name, string msg)
{
System.Diagnostics.Debug.WriteLine($"ShowMsg=> name:{name},msg:{msg}");
var eventMsg = new EventMessage
{
Name = name,
Msg = msg,
CreatedDate = DateTime.Now
};
EventPublishSubscribeUtils.PublishEvent(eventMsg, nameof(DemoB.ShowMsg));
}
}
//main方法中使用:
var demoA = new DemoA();
var demoB = new DemoB();
demoB.ShowMsg("放假通知", "世界那么大,我想去看看。");
从上述示例代码中可以看出,DemoA与DemoB各为独立,互不依赖,它们都不知道有对方的存在,它们只关心业务的处理,通过执行demoB.ShowMsg方法进而触发回调demoA.EventCallback1,demoA.EventCallback2方法,是不是比起直接从DemoA中调DemoB更好呢?
通过简单的关系图来对比未引用EventPublishSubscribeUtils前与引用后的区别。
来源链接:https://www.cnblogs.com/chenshibao/p/18850559
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容