最近对委托、事件的订阅使用的太多,订阅与被订阅之间的绑定约束非常...麻烦,所以翻了下MVVMLight源码找出这段可以拿出来用的部分,详情见下:
一.开发中遇到的问题:
场景1:ClassA中存在事件OnDataChanged,在数据发生改变时调用OnDataChanged事件通知其订阅者ClassB做相应处理
- 实现过程一般分如下几种
- ClassB中有ClassA的实例,然后订阅事件
- ClassA是单例模式,可以直接在ClassB中订阅单例ClassA的实例事件
- ClassA、ClassB的实例在一个共同的对象中,ClassB订阅ClassA的实例事件
问题:发生订阅这件事儿永远都需要前提条件,订阅方与被订阅方必须直接接触到才可以实现该逻辑,这样在不需要订阅与被订阅的对象接触时就不好处理逻辑了
场景2:A、B两个人合作,分别写订阅方逻辑、被订阅方逻辑
实现过程中,会遇到如下问题:
- B需要依赖A必须先写好订阅事件才可以开始自己的工作
- 在A、B双方对事件的参数、命名等发生修改时必须及时通知对方并要求对方立即更正,否则无法实现编译、调试和运行
二.MVVMLight中消息通知机制的对外实现
- 框架下对所有对象提供单例Messenger工具类,任何需要订阅、被订阅(发送、接收事件消息)的对象都通过对Messenger进行调用实现
- 避免了订阅方与被订阅方必须实例接触的问题了
- 调用方式上,在发送和接收用如下参数定义方式实现
/// <summary>
/// 注册订阅事件 /// </summary> /// <typeparam name="TMessage">传参类型</typeparam> /// <param name="recipient">订阅实例</param> /// <param name="token">发送与接收定义的key值</param> /// <param name="action">订阅事件触发的action</param> /// <param name="keepTargetAlive">持续控制实例存在,防止被回收清除</param> public virtual void Register<TMessage>(object recipient,object token,Action<TMessage> action,bool keepTargetAlive = false)/// <summary>
/// 被订阅方触发事件 /// </summary> /// <typeparam name="TMessage">传参类型</typeparam> /// <param name="message">参数数据</param> /// <param name="token">key</param> public virtual void Send<TMessage>(TMessage message, object token)例
public class Class1 { public Class1() { MessageTool.Messenger.Default.Register(this, "key", DataChangedHandle); } //订阅触发事件 public void DataChangedHandle(string obj) { //dosomething } /// ///对外通知事件消息 /// public void SendMessage() { MessageTool.Messenger.Default.Send("Message", "key"); } }
逻辑解释:
- 订阅时传参的“Key”是发送与接收之间唯一的key值,它的类型是object类型,也就是说可以根据自身需求进行设置key值类型
- Messenger其内部逻辑是在对Key值和传参类型进行比对,完全符合时才会调用订阅方实例的action
- Messenger有多重重载,订阅时不设置key,对任何传参类型相同的调用都接收触发,详情找机会下次分享
优点:避免订阅与被订阅的实例接触、事件参数命名发生改变时影响变小,最多触发不到,不会影响编译
缺点:我看到的必须有传参,即使null也可以,但必须有
下一节对这段源码拿出来看下什么情况,挖坑待填
接上文: