首頁 > 軟體

C#微信公眾號開發之使用者上下文WeixinContext和MessageContext

2022-06-15 14:00:41

概述

由於微信公眾平臺的特殊機制,所有的資訊都由微信伺服器轉發而來,因此伺服器是無法使用Session對使用者對談的上下文進行管理的。

為此Senparc.WeiXin.MP SDK增加了上下文的模組,並整合到了MessageHandler中。

WeixinContext

WeixinContext是所有單個使用者上下文(MessageContext)實體的容器(暫且稱為全域性上下文)。WeixinContext本身不是靜態類,意味著您可以在同一個應用中建立多個上下文實體。

同時,一個靜態的WeixinContext範例被放入到MessageHandler<TM>中,因此所有專案中由MessageHandler<TM>派生的子類中的WeixinContext是唯一的、全域性的(注:TM為實現IMessageContext的類,包括SDK中已經提供的MessageContext)。

因此我們在任何一個實現了MessageHandler<TM>的範例中(比如叫MyMessageHandler),都可以存取到一個型別和名稱都叫WeixinContext的物件。

WeixinContext用於儲存所使用者的上下文(MessageContext),並且提供了一系列的方法,主要方法包括:

        /// <summary>
        /// 重置所有上下文引數,所有記錄將被清空
        /// </summary>
        public void Restore()
        {
            ...
        }

        /// <summary>
        /// 獲取MessageContext,如果不存在,返回null
        /// 這個方法的更重要意義在於操作TM佇列,及時移除過期資訊,並將最新活動的物件移到尾部
        /// </summary>
        /// <param name="userName">使用者名稱(OpenId)</param>
        /// <returns></returns>
        private TM GetMessageContext(string userName)
        {
            ...
        }

        /// <summary>
        /// 獲取MessageContext
        /// </summary>
        /// <param name="userName">使用者名稱(OpenId)</param>
        /// <param name="createIfNotExists">True:如果使用者不存在,則建立一個範例,並返回這個最新的範例
        /// False:使用者儲存在,則返回null</param>
        /// <returns></returns>
        private TM GetMessageContext(string userName, bool createIfNotExists)
        {
            ...
        }


        /// <summary>
        /// 獲取MessageContext,如果不存在,使用requestMessage資訊初始化一個,並返回原始範例
        /// </summary>
        /// <returns></returns>
        public TM GetMessageContext(IRequestMessageBase requestMessage)
        {
            ...
        }

        /// <summary>
        /// 獲取MessageContext,如果不存在,使用requestMessage資訊初始化一個,並返回原始範例
        /// </summary>
        /// <returns></returns>
        public TM GetMessageContext(IResponseMessageBase responseMessage)
        {
            ...
        }

        /// <summary>
        /// 記錄請求資訊
        /// </summary>
        /// <param name="requestMessage">請求資訊</param>
        public void InsertMessage(IRequestMessageBase requestMessage)
        {
            ...
        }

        /// <summary>
        /// 記錄響應資訊
        /// </summary>
        /// <param name="responseMessage">響應資訊</param>
        public void InsertMessage(IResponseMessageBase responseMessage)
        {
            ...
        }

        /// <summary>
        /// 獲取最新一條請求資料,如果不存在,則返回Null
        /// </summary>
        /// <param name="userName">使用者名稱(OpenId)</param>
        /// <returns></returns>
        public IRequestMessageBase GetLastRequestMessage(string userName)
        {
            ...
        }

        /// <summary>
        /// 獲取最新一條響應資料,如果不存在,則返回Null
        /// </summary>
        /// <param name="userName">使用者名稱(OpenId)</param>
        /// <returns></returns>
        public IResponseMessageBase GetLastResponseMessage(string userName)
        {
            ...
        }

WeixinContext中有兩個用於儲存使用者上下文的物件:MessageCollection及MessageQueue。

這兩個物件中的元素集合是重合的,但是MessageQueue對元素進行了排序,以便及時處理掉頂部過期的上下文。

ExpireMinutes用於定義上下文時間有效期,預設為90分鐘。可以在程式的任何地方設定設個引數,且立即生效。

PS:MessageQueue中刪除過期資料的邏輯以極高的效率運作,開發時無需考慮CPU佔用及物件衝突的問題(額外校驗時間是否超時)。

MessageContext

MessageContext用於儲存單個使用者的上下文資訊,被儲存在WeixinContext的MessageCollection及MessageQueue物件中。 IMessageContext定義如下:

    public interface IMessageContext
    {
        /// <summary>
        /// 使用者名稱(OpenID)
        /// </summary>
        string UserName { get; set; }
        /// <summary>
        /// 最後一次活動時間(使用者主動傳送Resquest請求的時間)
        /// </summary>
        DateTime LastActiveTime { get; set; }
        /// <summary>
        /// 接收訊息記錄
        /// </summary>
        List<IRequestMessageBase> RequestMessages { get; set; }
        /// <summary>
        /// 響應訊息記錄
        /// </summary>
        List<IResponseMessageBase> ResponseMessages { get; set; }
        /// <summary>
        /// 臨時儲存資料,如使用者狀態等,出於保持.net 3.5版本,這裡暫不使用dynamic
        /// </summary>
        object StorageData { get; set; }
    }

您可以根據自己的需要建立自己的類,實現這個介面,並且被WeixinContext使用。當然如果你的要求不是那麼特殊,而且你比較懶的話,SDK提供了一個預設的MessageContext實現:

    /// <summary>
    /// 微信訊息上下文(單個使用者)
    /// </summary>
    public class MessageContext : IMessageContext
    {
        public string UserName { get; set; }
        public DateTime LastActiveTime { get; set; }
        public List<IRequestMessageBase> RequestMessages { get; set; }
        public List<IResponseMessageBase> ResponseMessages { get; set; }

        public object StorageData { get; set; }

        public MessageContext()
        {
            /*
             * 注意:即使使用其他類實現IMessageContext,
             * 也務必在這裡進行下面的初始化,尤其是設定當前時間,
             * 這個時間關係到及時從快取中移除過期的訊息,節約記憶體使用
             */
            RequestMessages = new List<IRequestMessageBase>();
            ResponseMessages = new List<IResponseMessageBase>();
            LastActiveTime = DateTime.Now;
        }
    }

上面的程式碼根據註釋很好理解,需要說明一下的是StorageData。這是一個用於儲存任何和使用者上下文有關資料的容器,WeixinContext和IMessageContext沒有對它進行任何參照,完全由開發者決定裡面的內容(比如使用者執行到哪一步、或某個比較重要的位置資訊等等),類似於Session的作用。

到此這篇關於C#微信公眾號開發之使用者上下文的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com