Senparc.Weixin SDK v6.5 開始支持 .NET Core 3.0,並將微信消息上下文進行了大幅度的重構,支持了使用分布式緩存存儲上下文信息,這意味着在分布式系統中,現在 Senparc.Weixin SDK 也能提供跨服務器的上下文消息共享。
當前的分布式上下文支持依賴了 NeuChar 提供的跨平台消息上下文解決方案,因此在公眾號、小程序、企業微信中都已經默認支持此功能(開放平台接收的是系統推送,暫時沒有必要支持)。
本次升級對應 Senparc.Weixin.dll:v6.5.0,Senparc.Weixin.MP.dll:v16.8.0。
一、升級
本次升級也帶來了一些變化,如果您的系統是從舊版本升級到新版本,需要做一些修改或注意一些要點:列舉如下:
1、相關模塊中提供了 DefaultMessageContext:DefaultMpMessageContext、DefaultWxOpenMessageContext、DefaultWorkMessageContext。這是之前版本中,需要用戶自定義 CustomMessageContext 的默認實現。因此從現在開始,如果開發者不需要對上下文進行特殊的改寫處理,使用 Senparc.Weixin 官方默認的規則,已經無需再創建 CustomMessageContext,可以直接這樣定義 CustomMessageHandler:
using Senparc.Weixin.MP.MessageContexts; //... public partial class CustomMessageHandler : MessageHandler<DefaultMpMessageContext> { //.... }
2、注意:您仍然可以使用先前定義的 CustomMessageContext,不過其中所包含的 CustomMessageContext_MessageContextRemoved() 方法將被忽略(因為系統無法收到緩存過期的通知)。這一點在技術上可以實現,只是在當前版本中暫未提供。解決的方法是使用一個外部的隊列或者線程,嚴格同步緩存信息,並及時向系統廣提示信號。
如果您已經創建了 CustomMessageContext,並希望繼續使用它們,請將基類從原先的:
public class CustomMessageContext : MessageContext<IRequestMessageBase, IResponseMessageBase> { //... }
變更為:
public class CustomMessageContext : DefaultMpMessageContext { //... }
命名空間:Senparc.Weixin.MP.MessageContexts。
如果是小程序或企業微信,則將上述 DefaultMpMessageContext 改為 DefaultWxOpenMessageContext 或 DefaultWorkMessageContext。
3、RequestMessageFactory.GetRequestEntity() 方法現在要求提供上下文實例。
之前可以使用如下代碼獨立於 MessageHandler 生成一個 RequestMessage 對象:
var requestDoc = XDocument.Load(Request.InputStream); var requestMessage = RequestMessageFactory.GetRequestEntity(requestDoc);
現在需要加入一個確定的上下文對象:
var requestDoc = XDocument.Load(Request.InputStream); var requestMessage = RequestMessageFactory.GetRequestEntity(new DefaultMpMessageContext(), requestDoc);
當然,您也仍然可以使用自己定義的 CustomMessageContext。
4、原先的 MessageHandler 中提供了 GlobalWeixinContext 屬性,用於在本地內存中儲存所有的上下文信息,現在由於已經升級為分布式緩存,因此已經沒有此對象。
在 MessageHandler 內部可以通過 base.GetCurrentMessageContext() 方法獲取當前用戶的上下文信息(示例),原先的 base.CurrentMessageContext 屬性已經過期,請勿再使用。
注意:無論是已經過期的 GetCurrentMessageContext 屬性還是新的 GetCurrentMessageContext() 方法,每次訪問都會從緩存讀取,這意味着如果你使用了分布式緩存,並且需要反復讀取當前用戶上下文信息,建議使用一個局部變量先讀取出來,然后再處理,例如:
var currentMessageContext = base.GetCurrentMessageContext(); if (currentMessageContext.RequestMessages.Count > 1) { result.AppendFormat("您剛才還發送了如下消息({0}/{1}):\r\n", currentMessageContext.RequestMessages.Count, currentMessageContext.StorageData); for (int i = currentMessageContext.RequestMessages.Count - 2; i >= 0; i--) { var historyMessage = currentMessageContext.RequestMessages[i]; result.AppendFormat("{0} 【{1}】{2}\r\n", historyMessage.CreateTime.ToString("HH:mm:ss"), historyMessage.MsgType.ToString(), (historyMessage is RequestMessageText) ? (historyMessage as RequestMessageText).Content : "[非文字類型]" ); } result.AppendLine("\r\n"); }
如果需要在 MessageHandler 外部獲取某個用戶的上下文信息,則可以這樣做:
//創建 GlobalMessageContext 對象 var globalMessageContext = new GlobalMessageContext<DefaultMpMessageContext, IRequestMessageBase, IResponseMessageBase>(); var openId = "<Your OpenId>"; var myMessageContext = globalMessageContext.GetMessageContext(openId);
二、新版本上下文架構及原理
將單獨發布文章介紹相關信息,盡情期待!