接上文 MVVMLight消息通知實現機制詳解(一)html
找到源碼看到,訂閱事件部分代碼:異步
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列表中post
源碼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
備註:在Send()部分應該加異步發送消息,我的自測頻率太快的調用會形成卡頓延遲(相似心跳包這種就有點費勁)htm