MVVMLight消息通知實現機制詳解(二)

  接上文 MVVMLight消息通知實現機制詳解(一)html

  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列表中post

  2. 在其Value值上是List<WeakActionAndToken>類型,WeakActionAndToken包含本次訂閱事件的Action和Key值

  

  源碼Send部分代碼:spa

 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();
        }

  以上是源碼上發送事件消息代碼,其具體邏輯以下:.net

  • 根據傳參Type值在Dictionary<Type, List<WeakActionAndToken>>上查找對應List<WeakActionAndToken>列表
  • 而後對該列表內WeakActionAndToken進行匹配,對應Key值是否相同
  • 找到Key值相同的WeakActionAndToken執行其Action

 

  備註:在Send()部分應該加異步發送消息,我的自測頻率太快的調用會形成卡頓延遲(相似心跳包這種就有點費勁)htm

  源碼:MVVMLight的消息發送工具源碼,可單獨使用對象

相關文章
相關標籤/搜索