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);}}}
有兴趣的看上面的代码 , 封装代码上面简单全部给上,后面的消息通知都是基于上面的三个类实现的,比较核心 。5.2 代码整理第 5 节涉及到多窗体及多
Razor
组件了,需要创建一些目录存放这些文件,方便分类管理 。文章插图
- A:放
Message
,即一些消息通知类;
- B:放
Razor
组件,如果需要与Maui\Blazor Server(Wasm)
等共享Razor
组件,可以创建Razor类库
存储;
- C:放通用服务,这里只放了一个窗体管理静态类,实际情况可以放
Redis
服务、RabbitMQ
消息服务等;
- D:放
WPF
视图 , 本示例WPF窗体只是一个壳,承载BlazorWebView
使用;推荐阅读
- 暗区突围容器箱怎么获取
- 骁龙888和骁龙870性能对比-骁龙888和骁龙870哪个好
- 真我手表t1测评_真我手表t1测评表现
- 怎样防止别人蹭wifi(最强连网神器)
- wifi如何手机上防止别人蹭网(手机wifi已连接但不可上网)
- jvm双亲委派机制详解
- 信号量 C# 多线程访问之 SemaphoreSlim【C# 进阶】
- 2022支付宝蚂蚁庄园8月19日答案
- iqoo8pro散热怎么样_iqoo8pro散热效果好吗
- 原神纸间奇旅怎么玩