繁体   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