簡體   English   中英

如何使用 State 訪問器獲取 Bot Framework 中的屬性

[英]How to use State Accessors to get properties in Bot Framework

我的機器人的功能之一是處理購物車。 用戶可以在對話中的任何位置添加商品,然后完成購物以關閉產品購物車。

為避免將購物車從對話框傳遞到對話框,我想在UserState中創建一個UserProfile屬性( UserProfile屬性具有ShoppingCart屬性),但我不太清楚如何正確使用它。

我的主對話框包含一組子對話框,其中一些需要能夠訪問ShoppingCart object。 我在示例中找到了一些示例,但它們都沒有達到我想要的效果。 在 State 管理示例中:

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
        {
            // Get the state properties from the turn context.

            var conversationStateAccessors =  _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
            var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

            var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
            var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile());

            if (string.IsNullOrEmpty(userProfile.Name))
            {
                // First time around this is set to false, so we will prompt user for name.
                if (conversationData.PromptedUserForName)
                {   
                    // Set the name to what the user provided.
                    userProfile.Name = turnContext.Activity.Text?.Trim();

                    // Acknowledge that we got their name.
                    await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

                    // Reset the flag to allow the bot to go though the cycle again.
                    conversationData.PromptedUserForName = false;
                }
                else
                {
                    // Prompt the user for their name.
                    await turnContext.SendActivityAsync($"What is your name?");

                    // Set the flag to true, so we don't prompt in the next turn.
                    conversationData.PromptedUserForName = true;
                }
            }

如果我理解正確,每次他想要獲取訪問者時都會創建一個新屬性? 或者,如果您調用CreateProperty創建了一個屬性,則不會創建任何屬性並返回訪問器?

我曾想過在 Bot 上獲取訪問器,然后將其傳遞給MainDialog ,然后ChildDialogs ,但這有點違背了不通過對話框傳遞ShoppingCart的目的。

我不能在不必每次都創建屬性的情況下獲取訪問器嗎?

我讀過這個問題,它可以解決我的問題,但后來我看到@johnataylor的評論說

我們遵循的模式是將訪問器的創建推遲到我們需要它時——這似乎最有效地隱藏了固有的噪音。

如果我想在我的對話框中獲取ShoppingCart (位於我需要訪問的UserProfile屬性內),我應該何時創建訪問器?

快速回答:您應該在需要操作 state 的所有對話框中創建訪問器。

詳細答案:

CreateProperty不會物理地創建屬性,它只是:

創建一個屬性定義並將其注冊到此 BotState

CreateProperty()將返回一個BotStatePropertyAccessor ,您可以從中調用GetAsyncSetAsyncDeleteAsync ,它們將從轉彎上下文中的 state 緩存中獲取、設置和刪除屬性。(內部緩存機器人狀態)

當您調用BotState.SaveChangesAsync()這將:

如果它已更改,則將在當前上下文 object 中緩存的 state object 寫入存儲。

每次調用GetAsyncSetAsync實際上都會首先調用BotState.LoadAsync()來:

讀取當前的 state object 並將其緩存在上下文 object 中以供本回合使用。

並且當調用 GetAsync()並且沒有找到鍵時,它將自動調用SetAsync來設置該新屬性

如果您使用的是AutoSaveStateMiddleware ,該中間件將:

在回合結束時自動為它管理的所有 BotState class 調用.SaveChanges()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM