我的机器人的功能之一是处理购物车。用户可以在对话中的任何位置添加项目,然后完成购物以关闭产品购物车。
为了避免将购物车从对话框传递到对话框,我想在UserProfile
中创建UserState
属性(UserProfile
属性具有ShoppingCart
属性),但我不太清楚如何使用此属性正确。
我的主对话框包含一组子对话框,其中一些必须能够访问ShoppingCart
对象。我在示例中找到了一些示例,但是它们都没有达到我想要的目标。在状态管理示例中:
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
的目的。
我是否不必每次都创建属性就可以获取访问器?
我读过this issue,它为我的问题提供了解决方案,但随后我看到了[[@johnataylor的评论中说
我们遵循的模式是将访问器的创建推迟到我们需要它之前-这似乎最有效地隐藏了固有的噪声。
如果我想在对话框中获取ShoppingCart
(位于我需要访问的UserProfile
属性之内,我应该何时创建访问器?
快速回答:您应该在需要操纵状态的所有对话框中创建访问器。
详细答案:
CreateProperty
并不实际创建该属性,它只是:创建属性定义并在此BotState中注册它
CreateProperty()
将为您返回一个BotStatePropertyAccessor,您可以从中调用GetAsync,SetAsync和DeleteAsync,它们将从以下位置获取,设置和删除属性转弯上下文中的状态缓存。(内部缓存的漫游器状态)当您调用BotState.SaveChangesAsync()
时,这将:如果已更改,则将本次缓存在当前上下文对象中的状态对象写入存储。
每次
GetAsync
,SetAsync的调用实际上将首先调用BotState.LoadAsync()到:读取当前状态对象并将其缓存在上下文中此回合的对象。
并且当调用
GetAsync()
且找不到键时,它将自动调用SetAsync来设置该新属性如果您使用的是AutoSaveStateMiddleware
,则该中间件将:在回合结束时自动为所有人调用.SaveChanges()它正在管理的BotState类。