MVVMLight消息通知实现机制详解(二)
- 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型、Key值、Action、Target(订阅对象本身)
- 在发生订阅事件和触发订阅事件时都会调用通过查询上述字典进行匹配,找到Key值相同&&Type类型相同的值,执行target的action并传入参数
- 扩展1:可发生没有key值的订阅事件,只要传参类型相同就可以
- 扩展2:可发生静态类的订阅事件,其内部有判断是否为static,static时target可为空
找到源码看到,订阅事件部分代码:
public virtual void Register<TMessage>( object recipient,object token,bool receiveDerivedMessagesToo,Action<TMessage> action,bool keepTargetAlive = false)
{
lock (_registerLock)
{
var messageType = typeof(TMessage); Dictionary<Type, List<WeakActionAndToken>> recipients; if (receiveDerivedMessagesToo)
{
if (_recipientsOfSubclassesAction == null)
{
_recipientsOfSubclassesAction = new Dictionary<Type, List<WeakActionAndToken>>();
} recipients = _recipientsOfSubclassesAction;
}
else
{
if (_recipientsStrictAction == null)
{
_recipientsStrictAction = new Dictionary<Type, List<WeakActionAndToken>>();
} recipients = _recipientsStrictAction;
} lock (recipients)
{
List<WeakActionAndToken> list; if (!recipients.ContainsKey(messageType))
{
list = new List<WeakActionAndToken>();
recipients.Add(messageType, list);
}
else
{
list = recipients[messageType];
} var weakAction = new WeakAction<TMessage>(recipient, action, keepTargetAlive); var item = new WeakActionAndToken
{
Action = weakAction,
Token = token
}; list.Add(item);
}
} RequestCleanup();
}
以上是源码上订阅事件代码,其具体逻辑如下:
以Dictionary<Type, List<WeakActionAndToken>> 类型持有数据,对每一个订阅事件都是先在Dictionary的Key上查找是否存在该传参类型,不存在就添加该类型(Add(type,new List<WeakActionAndToken>)),存在就添加到该类型对应的Value列表中
- 在其Value值上是List<WeakActionAndToken>类型,WeakActionAndToken包含本次订阅事件的Action和Key值
源码Send部分代码:
private void SendToTargetOrType<TMessage>(TMessage message, Type messageTargetType, object token)
{
var messageType = typeof(TMessage); if (_recipientsOfSubclassesAction != null)
{
// Clone to protect from people registering in a "receive message" method
// Correction Messaging BL0008.002
var listClone =
_recipientsOfSubclassesAction.Keys.Take(_recipientsOfSubclassesAction.Count()).ToList(); foreach (var type in listClone)
{
List<WeakActionAndToken> list = null; if (messageType == type
|| messageType.IsSubclassOf(type)
|| type.IsAssignableFrom(messageType))
{
lock (_recipientsOfSubclassesAction)
{
list = _recipientsOfSubclassesAction[type].Take(_recipientsOfSubclassesAction[type].Count()).ToList();
}
} SendToList(message, list, messageTargetType, token);
}
} if (_recipientsStrictAction != null)
{
List<WeakActionAndToken> list = null; lock (_recipientsStrictAction)
{
if (_recipientsStrictAction.ContainsKey(messageType))
{
list = _recipientsStrictAction[messageType]
.Take(_recipientsStrictAction[messageType].Count())
.ToList();
}
} if (list != null)
{
SendToList(message, list, messageTargetType, token);
}
} RequestCleanup();
}
以上是源码上发送事件消息代码,其具体逻辑如下:
- 根据传参Type值在Dictionary<Type, List<WeakActionAndToken>>上查找对应List<WeakActionAndToken>列表
- 然后对该列表内WeakActionAndToken进行匹配,对应Key值是否相同
- 找到Key值相同的WeakActionAndToken执行其Action
备注:在Send()部分应该加异步发送消息,个人自测频率太快的调用会造成卡顿延迟(类似心跳包这种就有点费劲)
MVVMLight消息通知实现机制详解(二)的更多相关文章
- MVVMLight消息通知实现机制详解(一)
最近对委托.事件的订阅使用的太多,订阅与被订阅之间的绑定约束非常...麻烦,所以翻了下MVVMLight源码找出这段可以拿出来用的部分,详情见下: 一.开发中遇到的问题: 场景1:ClassA中存在事 ...
- Android的事件处理机制详解(二)-----基于监听的事件处理机制
基于监听的事件处理机制 前言: 我们开发的app更多的时候是需要与用户的交互----即对用户的操作进行响应 这就涉及到了android的事件处理机制; android给我们提供了两套功能强大的处理机制 ...
- 二,PHP缓存机制详解
一,PHP缓存机制详解 我们可以使用PHP自带的缓存机制来完成页面静态化,但是仅靠PHP自身的缓存机制并不能完美的解决页面静态化,往往需要和其他静态化技术(通常是伪静态技术)结合使用. output ...
- iOS的消息转发机制详解
iOS开发过程中,有一类的错误会经常遇到,就是找不到所调用的方法,当然这类问题比较好解决,给当前对象或其父类对象添加该方法即可,使得编译器在编译时能正确找到该方法:或者,还有另外的方法,由于Objec ...
- nginx平台初识(二) 浏览器 HTTP 协议缓存机制详解
1.缓存的分类 缓存分为服务端侧(server side,比如 Nginx.Apache)和客户端侧(client side,比如 web browser). 服务端缓存又分为 代理服务器缓存 和 反 ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- JVM类加载机制详解(二)类加载器与双亲委派模型
在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...
- [转]JavaScript异步机制详解
原文: https://www.jianshu.com/p/4ea4ee713ead --------------------------------------------------------- ...
- ssion机制详解
ssion机制详解 ref:http://justsee.iteye.com/blog/1570652 虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚sess ...
随机推荐
- 题解 洛谷P1501/BZOJ2631【[国家集训队]Tree II】
Link-Cut-Tree 的懒标记下传正确食用方法. 我们来逐步分析每一个操作. 1:+ u v c:将u到v的路径上的点的权值都加上自然数c; 解决方法: 很显然,我们可以 split(u,v) ...
- 洛谷——P1342 请柬
P1342 请柬 题目描述 在电视时代,没有多少人观看戏剧表演.Malidinesia古董喜剧演员意识到这一事实,他们想宣传剧院,尤其是古色古香的喜剧片.他们已经打印请帖和所有必要的信息和计划.许多学 ...
- Python学习:ModuleNotFoundError: No module named 'pygal.i18n' 的解决方法
最近在学<Python编程:从入门到实践>,16.2小结中 from pygal.i18n import COUNTRIES 获取两个字母的国别码,我用的pygal的版本是2.4.0(终端 ...
- Ubuntu挂载硬盘,修改卷标
Ubuntu挂载硬盘,修改卷标转载2016-03-06 17:03:21标签:ubuntu Ubuntu不像windows,硬盘插入电脑不会自动读取硬盘 数据,需要把硬盘挂载到文件夹上,然后才能访问硬 ...
- Java 字符串总结
三种字符串类:String,StringBuilder,StringBuffer String类 1. 常用构造器 构造器 public String(char value[]) public ...
- Stones HDU 1896
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1896 题目大意: 有n个石头,每个石头有:p 它所在的位置 ,d 它能扔多远 从0 开始,遇到第奇 ...
- 从一行代码开始,浅谈python字符串格式化
今天看到了一行这样的代码: boundary = '%.32x' % random.randint(0, 256**16) 我知道这是一个生成格式化字符串的语句,它将随机生成的一个32位16进制数,将 ...
- 【Chrome】Chrome浏览器怎么查看版本信息
第一步,打开Chrome浏览器 第二步,弹出浏览器主界面 第三步,点击右上按钮(三横杠) 第四步,下拉中选择“关于” 第五步,弹出窗口,可以看到版本信息 第二种方法: 第六步,也可以通过地址栏里输入命 ...
- O - Treats for the Cows 区间DP
FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast am ...
- spring项目启动需要的几个注解
1.@ComponentScan注解,spring context包下,可以理解嘛,扫描srping bean放在ioc容器中的. ApplicationContext是接口,就是IOC容器嘛,也在这 ...