接上文 MVVMLight消息通知实现机制详解(一)

  1. 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型、Key值、Action、Target(订阅对象本身)
  2. 在发生订阅事件和触发订阅事件时都会调用通过查询上述字典进行匹配,找到Key值相同&&Type类型相同的值,执行target的action并传入参数
  3. 扩展1:可发生没有key值的订阅事件,只要传参类型相同就可以
  4. 扩展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();
        }

  以上是源码上订阅事件代码,其具体逻辑如下:

  1. 以Dictionary<Type, List<WeakActionAndToken>> 类型持有数据,对每一个订阅事件都是先在Dictionary的Key上查找是否存在该传参类型,不存在就添加该类型(Add(type,new List<WeakActionAndToken>)),存在就添加到该类型对应的Value列表中

  2. 在其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的消息发送工具源码,可单独使用

 

posted on 2018-12-10 17:05  Khandasas  阅读(1009)  评论(0编辑  收藏  举报