博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MvvmLight的Message使用
阅读量:4686 次
发布时间:2019-06-09

本文共 7104 字,大约阅读时间需要 23 分钟。

MvvmLight 的消息系统是比较强大的,我们通过使用它来进一步了解它内部的实现。之前Mgen的已经介绍过它的一些用法。

我们先定义基于ViewModelBase的类,暂且叫他TestPorpertyChangedViewModel:

public class TestPorpertyChangedViewModel:ViewModelBase        {            public TestPorpertyChangedViewModel()            {                Messenger.Default.Register
>(this, msg => DebugInfo(msg)); RaisePropertyChanged("Prop", "John", "Zhang", true);//调用上面注册的msg => PrintInfo(msg); } public void DebugInfo(object obj) { var str = string.Empty; foreach (var prop in obj.GetType().GetProperties()) { str += string.Format("{0}: {1}{2}", prop, prop.GetValue(obj, null), Environment.NewLine); } Debug.WriteLine("========"); Debug.WriteLine(str); } public const string PropPropertyName = "Prop"; private string _prop; public string Prop { get { return _prop; } set { if (_prop == value) { return; } var oldValue = _prop; _prop = value; //RaisePropertyChanged(PropPropertyName, oldValue, value, true); } } }

为了测试方便,我们在构造函数里调用了 Messager的注册操作,并且执行消息,其实就是调用ViewModelBase的BroadCast方法。

Messenger.Default.Register
>(this, msg => DebugInfo(msg)); RaisePropertyChanged("Prop", "John", "Zhang", true);//调用上面注册的msg => PrintInfo(msg);

然后我们就可以写测试代码了.就一句代码搞定:

[TestMethod]public void TestPropertyChangedMsg(){    TestPorpertyChangedViewModel test = new TestPorpertyChangedViewModel();}
执行上述代码就可以在调试窗口里看见:

接下来我们就来分析下MvvmLight到底调用了哪些方法呢?

首先就是调用IMessager类的Register函数:

void Register
(object recipient, Action
action);

Messager类里是如此实现的:

public virtual void Register
(object recipient, Action
action){ Register(recipient, null, false, action);}
public virtual void Register
(//TMessage接受的类型 object recipient,//接收的对象一般是viewmodel object token,//标记,细分类型下面的分类 bool receiveDerivedMessagesToo,//是否也接收 (派生类)消息 Action
action)//当有消息来的时候 回调函数{ lock (_registerLock)//锁住_registerLock,多线程锁 { Type messageType = typeof(TMessage);//消息类型 Dictionary
> recipients;//定义存储容器recipients if (receiveDerivedMessagesToo)//判断是否接受继承的消息 { if (_recipientsOfSubclassesAction == null) { _recipientsOfSubclassesAction = new Dictionary
>(); } recipients = _recipientsOfSubclassesAction;//把继承的消息字典附给recipients原始容器 } else { if (_recipientsStrictAction == null) { _recipientsStrictAction = new Dictionary
>(); } recipients = _recipientsStrictAction; } lock (recipients)//锁住 { List
list; if (!recipients.ContainsKey(messageType))//判断容器中是否包含messageType { list = new List
();//定义新的WeakActionAndToken集合 recipients.Add(messageType, list);//不包含的话添加 } else { list = recipients[messageType];//把该messageType的Value附给list } var weakAction = new WeakAction
(recipient, action); var item = new WeakActionAndToken { Action = weakAction,//weakAction附给weakActionAndToken Token = token }; list.Add(item);//把item添加进list集合 } } RequestCleanup();//请求清除资源。}

其实说的简单点就是添加进集合,接下来我们看看RaisePropertyChanged函数,就是去调用它的weakAction了。

protected virtual void Broadcast
(T oldValue, T newValue, string propertyName){ var message = new PropertyChangedMessage
(this, oldValue, newValue, propertyName); MessengerInstance.Send(message);}

我们看到其实也就是调了MessageInstance.Send(message)方法啊。

private void SendToTargetOrType
(TMessage message, Type messageTargetType, object token){ Type messageType = typeof(TMessage); if (_recipientsOfSubclassesAction != null) { // Clone to protect from people registering in a "receive message" method // Correction Messaging BL0008.002 List
listClone = _recipientsOfSubclassesAction.Keys.Take(_recipientsOfSubclassesAction.Count()).ToList(); foreach (Type type in listClone) { List
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) { lock (_recipientsStrictAction) { if (_recipientsStrictAction.ContainsKey(messageType)) { var list = _recipientsStrictAction[messageType] .Take(_recipientsStrictAction[messageType].Count()) .ToList(); SendToList(message, list, messageTargetType, token); } } } RequestCleanup();}

因为我们在注册消息的时候是使用默认的不注册派生类的所以实际我们调用的是:

if (_recipientsStrictAction != null){    lock (_recipientsStrictAction)    {        if (_recipientsStrictAction.ContainsKey(messageType))        {            var list = _recipientsStrictAction[messageType]                .Take(_recipientsStrictAction[messageType].Count())                .ToList();            SendToList(message, list, messageTargetType, token);        }    }}
看看SendToList这个静态私有方法:
private static void SendToList
( TMessage message, IEnumerable
list, Type messageTargetType, object token){ if (list != null) { // Clone to protect from people registering in a "receive message" method // Correction Messaging BL0004.007 List
listClone = list.Take(list.Count()).ToList(); foreach (WeakActionAndToken item in listClone) { var executeAction = item.Action as IExecuteWithObject; if (executeAction != null && item.Action.IsAlive && item.Action.Target != null && (messageTargetType == null || item.Action.Target.GetType() == messageTargetType || messageTargetType.IsAssignableFrom(item.Action.Target.GetType())) && ((item.Token == null && token == null) || item.Token != null && item.Token.Equals(token))) { executeAction.ExecuteWithObject(message); } } }}
其实也就是遍历调用了WeakAction泛型类的ExecuteWithObject方法,里面也就是调用了我们定义的委托。
关键就是遍历消息类型,找到这个注册的PropertyChangedMessage。

下篇我们详细剖析下各个方法的实现。

转载于:https://www.cnblogs.com/johnwonder/archive/2012/12/16/2820889.html

你可能感兴趣的文章
反射,invoke()
查看>>
iServer6R使用WMTS自定义比例尺出图
查看>>
pinyin4j的使用
查看>>
Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法
查看>>
tcpcopy用法
查看>>
34个加速页面载入速度的技巧
查看>>
MAC Objective-C 开发经典书籍推荐
查看>>
OSGi bundle之间互相通信的方法
查看>>
C++ 沉思录——Chap8:一个面向对象程序范例
查看>>
.NET 的编码
查看>>
数据存储——手机内部文件存储
查看>>
HDU 2586 LCA
查看>>
linux安装openldap步骤
查看>>
九度OJ 1035:找出直系亲属(二叉树)
查看>>
hive left outer join的问题
查看>>
32位Win7下安装与配置PHP环境(二)
查看>>
图片、浏览器-HTML5/CSS3系列教程:使用SVG图片-by小雨
查看>>
[学习笔记]node.js中的path.extname方法
查看>>
[学习笔记]HTTP协议
查看>>
警告:Assigning to 'id<Delegate>' from incompatible type 'ViewController *const_st
查看>>