MvvmLight的Messager源码阅读,简单封装了一个Messager,可以适用于一般的业务需求 。
5.1 Messager封装本来不想贴代码直接给源码链接的,想想代码也不多,直接上吧 。
Message
消息抽象类,用于定义消息类型,具体的消息需要继承该类,比如后面的打开子窗体消息OpenSecondViewMessage 。
using System;namespace WPFBlazorChat.Messages;public abstract class Message{protected Message(object sender){this.Sender = sender ?? throw new ArgumentNullException(nameof(sender));}public object Sender { get; }}IMessenger
消息接口,只定义了三个接口:
- Subscribe:消息订阅
- Unsubscribe:取消消息订阅
- Publish:消息发送
using System;namespace WPFBlazorChat.Messages;public interface IMessenger{void Subscribe<TMessage>(object recipient, Action<TMessage> action,ThreadOption threadOption = ThreadOption.PublisherThread) where TMessage : Message;void Unsubscribe<TMessage>(object recipient, Action<TMessage>? action = null) where TMessage : Message;void Publish<TMessage>(object sender, TMessage message) where TMessage : Message;}public enum ThreadOption{PublisherThread,BackgroundThread,UiThread}Messenger消息的管理,消息中转等实现:
using System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Threading.Tasks;namespace WPFBlazorChat.Messages;public class Messenger : IMessenger{public static readonly Messenger Default = new Messenger();private readonly object registerLock = new object();private Dictionary<Type, List<WeakActionAndToken>>? recipientsOfSubclassesAction;public void Subscribe<TMessage>(object recipient, Action<TMessage> action, ThreadOption threadOption)where TMessage : Message{lock (this.registerLock){var messageType = typeof(TMessage);this.recipientsOfSubclassesAction ??= new Dictionary<Type, List<WeakActionAndToken>>();List<WeakActionAndToken> list;if (!this.recipientsOfSubclassesAction.ContainsKey(messageType)){list = new List<WeakActionAndToken>();this.recipientsOfSubclassesAction.Add(messageType, list);}else{list = this.recipientsOfSubclassesAction[messageType];}var item = new WeakActionAndToken{ Recipient = recipient, ThreadOption = threadOption, Action = action };list.Add(item);}}public void Unsubscribe<TMessage>(object? recipient, Action<TMessage>? action) where TMessage : Message{var messageType = typeof(TMessage);if (recipient == null || this.recipientsOfSubclassesAction == null ||this.recipientsOfSubclassesAction.Count == 0 || !this.recipientsOfSubclassesAction.ContainsKey(messageType)){return;}var lstActions = this.recipientsOfSubclassesAction[messageType];for (var i = lstActions.Count - 1; i >= 0; i--){var item = lstActions[i];var pastAction = item.Action;if (pastAction != null&& recipient == pastAction.Target&& (action == null || action.Method.Name == pastAction.Method.Name)){lstActions.Remove(item);}}}public void Publish<TMessage>(object sender, TMessage message) where TMessage : Message{var messageType = typeof(TMessage);if (this.recipientsOfSubclassesAction != null){var listClone = this.recipientsOfSubclassesAction.Keys.Take(this.recipientsOfSubclassesAction.Count).ToList();foreach (var type in listClone){List<WeakActionAndToken>? list = null;if (messageType == type || messageType.IsSubclassOf(type) || type.IsAssignableFrom(messageType)){list = this.recipientsOfSubclassesAction[type].Take(this.recipientsOfSubclassesAction[type].Count).ToList();}if (list is { Count: > 0 }){this.SendToList(message, list);}}}}private void SendToList<TMessage>(TMessage message, IEnumerable<WeakActionAndToken> weakActionsAndTokens)where TMessage : Message{var list = weakActionsAndTokens.ToList();var listClone = list.Take(list.Count()).ToList();foreach (var item in listClone){if (item.Action is { Target: { } }){switch (item.ThreadOption){case ThreadOption.BackgroundThread:Task.Run(() => { item.ExecuteWithObject(message); });break;case ThreadOption.UiThread:SynchronizationContext.Current!.Post(_ => { item.ExecuteWithObject(message); }, null);break;default:item.ExecuteWithObject(message);break;}}}}}public class WeakActionAndToken{public object? Recipient { get; set; }public ThreadOption ThreadOption { get; set; }public Delegate? Action { get; set; }public string? Tag { get; set; }public void ExecuteWithObject<TMessage>(TMessage message) where TMessage : Message{if (this.Action is Action<TMessage> factAction){factAction.Invoke(message);}}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 高铁能带1000ml的洗发水吗
- 宽带网络电视怕打雷吗
- 藕粉颗粒状的好还是粉状的
- 裙带菜泡发后可以直接吃吗
- 水质检测多少数值合格
- 蛋糕粉做馒头要不要加酵母
- 钠钙玻璃杯能倒开水吗
- 洗衣机怎么清理里面的脏东西
- 五仁馅料怎么做更松软
- 煮带壳花生放什么调料
