简体   繁体   English

如何使用 State 访问器获取 Bot Framework 中的属性

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

One of the functionalities of my bot is handling a Shopping Cart.我的机器人的功能之一是处理购物车。 The user can add items anywhere in the conversation and then finish shopping to close the product cart.用户可以在对话中的任何位置添加商品,然后完成购物以关闭产品购物车。

To avoid passing the cart from dialog to dialog I would like to create a UserProfile property in the UserState (The UserProfile property has a ShoppingCart attribute) but I don't quite know how to use this properly.为避免将购物车从对话框传递到对话框,我想在UserState中创建一个UserProfile属性( UserProfile属性具有ShoppingCart属性),但我不太清楚如何正确使用它。

My Main Dialog contains a set of Child Dialogs and some of them need to be able to access the ShoppingCart object.我的主对话框包含一组子对话框,其中一些需要能够访问ShoppingCart object。 I found some examples in the samples but none of them do what I want to achieve.我在示例中找到了一些示例,但它们都没有达到我想要的效果。 In the State Management sample:在 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;
                }
            }

If I understand correctly, every time he wants to get the accessor a new Property is created?如果我理解正确,每次他想要获取访问者时都会创建一个新属性? Or once a property is created if you call CreateProperty no property will be creater and the accessor is returned?或者,如果您调用CreateProperty创建了一个属性,则不会创建任何属性并返回访问器?

I thought about getting the accessor on the Bot and then passing it to MainDialog and then to the ChildDialogs but it kinda defeats the purpose of not passing the ShoppingCart through Dialogs.我曾想过在 Bot 上获取访问器,然后将其传递给MainDialog ,然后ChildDialogs ,但这有点违背了不通过对话框传递ShoppingCart的目的。

Can't I get the accessors without having to create a Property every time?我不能在不必每次都创建属性的情况下获取访问器吗?

I've readthis issue which gives a solution to my problem, but then I saw @johnataylor 's comment saying我读过这个问题,它可以解决我的问题,但后来我看到@johnataylor的评论说

The pattern we follow is to defer the creation of the accessor until we need it - this seems to hide the inherent noise the most effectively.我们遵循的模式是将访问器的创建推迟到我们需要它时——这似乎最有效地隐藏了固有的噪音。

When should I create the accessors if I want to get the ShoppingCart (which is inside the UserProfile property that I need to access) inside my Dialogs?如果我想在我的对话框中获取ShoppingCart (位于我需要访问的UserProfile属性内),我应该何时创建访问器?

Fast Answer: You should create the accessor in the all the dialogs where you need to manipulate the state.快速回答:您应该在需要操作 state 的所有对话框中创建访问器。

Detailed Answer:详细答案:

CreateProperty does not physically create the property, it just: CreateProperty不会物理地创建属性,它只是:

Creates a property definition and register it with this BotState创建一个属性定义并将其注册到此 BotState

CreateProperty() will return you a BotStatePropertyAccessor from which you can call GetAsync , SetAsync and DeleteAsync those will Get, Set and delete a property from the state cache in the turn context.(Internal cached bot state) CreateProperty()将返回一个BotStatePropertyAccessor ,您可以从中调用GetAsyncSetAsyncDeleteAsync ,它们将从转弯上下文中的 state 缓存中获取、设置和删除属性。(内部缓存机器人状态)

When you call BotState.SaveChangesAsync() this will:当您调用BotState.SaveChangesAsync()这将:

If it has changed, writes to storage the state object that is cached in the current context object for this turn.如果它已更改,则将在当前上下文 object 中缓存的 state object 写入存储。

Each call of GetAsync , SetAsync will actually call BotState.LoadAsync() first to:每次调用GetAsyncSetAsync实际上都会首先调用BotState.LoadAsync()来:

Reads in the current state object and caches it in the context object for this turn.读取当前的 state object 并将其缓存在上下文 object 中以供本回合使用。

And when GetAsync() is called and no key is found , it will automatically call SetAsync to set that new property并且当调用 GetAsync()并且没有找到键时,它将自动调用SetAsync来设置该新属性

If you are using AutoSaveStateMiddleware that middleware will:如果您使用的是AutoSaveStateMiddleware ,该中间件将:

automatically call.SaveChanges() at the end of the turn for all BotState class it is managing.在回合结束时自动为它管理的所有 BotState class 调用.SaveChanges()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在对话框中使用Bot状态访问器 - Using Bot State Accessors Inside Dialogs 如何使用“委托”访问器创建属性? - How to create properties with “delegated” accessors? 我应该在我的C#程序中使用属性还是应该使用get / set访问器? - Should I use properties in my C# programs or should I use get/set accessors? 事件处理程序访问器/属性的确切用途是什么? - What exactly is the use of event handler accessors/properties? 如何摆脱警告“不建议将Bot Framework State API用于生产环境,并且可能在将来的版本中弃用。” - How to get rid of the warning “Bot Framework State API is not recommended for production environments, and may be deprecated in a future release.” 实体框架-定义没有集合访问器的get - Entity Framework - defining get without set accessors 尝试在get和set访问器中使用值的方法会产生.Net框架错误 - Trying to use methods on values within get and set accessors gives a .Net framework error 我如何使用访问器? - How do I use accessors? 如何声明获取访问器和/或设置访问器以检索列表? - How can I declare get accessors and/or set accessors to retrieve lists? 如何在Microsoft Bot Framework中使用全局命令? - How to use Global Commands in Microsoft Bot Framework?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM