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 ...
随机推荐
- Linux 安装 MySQL 详解(rpm 包)
说明:Linux 系统中软件的安装在 root 用户下进行,此安装方式为 rpm 包方式,安装的版本为:MySQL-5.6.25-1.linux_glibc2.5.x86_64.rpm-bundle. ...
- git 连接github.com 并配置密钥
传送门:http://www.jianshu.com/p/ff1034ed270e #备份ssh cd ~/.ssh $ ls $ mkdir key_backup //创建备份文件夹 $ cp id ...
- The turtle Module 一个画图的模块
感悟: 这样写的介绍才有用 import turtle bob = turtle.Turtle() print(bob) turtle.mainloop() Turtle()方法打开一个窗口,中间带有 ...
- centos7在grub界面下更改root密码
想要更改root的密码或者忘记了root的密码的时候可以在grub界面下更改root的密码. 百度了很多内容,更多方法都是适用于centos6及以前版本的,终于找到一个可以的. 1.开机后,在下图界面 ...
- BZOJ 4415 洛谷 3988 [Shoi2013]发牌
[题解] 权值线段树.查询当前牌堆顶的牌并且删掉就好了. #include<cstdio> #include<algorithm> #define N 3000010 #def ...
- 782B The Meeting Place Cannot Be Changed(二分)
链接:http://codeforces.com/problemset/problem/782/B 题意: N个点,需要找到一个点使得每个点到这个点耗时最小,每个点都同时开始,且都拥有自己的速度 题解 ...
- Nginx学习总结(3)——Nginx配置及应用场景之高级配置
一.Nginx反向代理 反向代理(Reverse Proxy)方式是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器:并将从服务器上得到的结果返回给Internet ...
- noip模拟赛 传球接力
[问题描述]n 个小朋友在玩传球. 小朋友们用 1 到 n 的正整数编号. 每个小朋友有一个固定的传球对象,第 i 个小朋友在接到球后会将球传给第 ai个小朋友, 并且第 i 个小朋友与第 ai个小朋 ...
- 【Tomcat】tomcat配置多域名和虚拟路径
当我们用浏览器在访问网页的时候,如访问www.baidu.com,一般都认为会在DNS服务器上找这个域名对应的IP,然后向这个IP发送请求 并响应,其实在DNS服务器解析之前,本机会先在你的系统配置文 ...
- 又见GCD
Problem Description 有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b.若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c. Input ...