c# - 从 DialogContext 获取 TurnState 数据
问题描述
我正在使用 BotBuilder SDK v4。这是下面的解释(忽略一些额外的代码)。
在我的机器人上OnTurnAsync
,我正在像这样调用我的一个对话框。
public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
var state = await _accessors.TurnStateAccessor.GetAsync(turnContext, () => new TurnState()).ConfigureAwait(false);
var dialogContext = await _dialogs.CreateContextAsync(turnContext).ConfigureAwait(false);
await dialogContext.BeginDialogAsync(nameof(SomeDialog)).ConfigureAwait(false);
//remaining code..
}
调用成功并到达对话框。下面是代码。
public override Task<DialogTurnResult> BeginDialogAsync(DialogContext outerDc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{
outerDc.ContinueDialogAsync();
return base.BeginDialogAsync(outerDc, options, cancellationToken);
}
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
{
var turnState = outerDc.Context.TurnState["ConversationState"]; //access turn state here
outerDc.EndDialogAsync();
return base.ContinueDialogAsync(outerDc, cancellationToken);
}
在内部ContinueDialogAsync
,我试图访问outerDc
包含我的机器人状态数据的对话框的上下文对象,正如我在即时/监视窗口中配置和看到的那样。
outerDc.Context.TurnState Count = 3
[0]: {[BotIdentity, System.Security.Claims.ClaimsIdentity]}
[1]: {[Microsoft.Bot.Connector.IConnectorClient, Microsoft.Bot.Connector.ConnectorClient]}
[2]: {[ConversationState, Microsoft.Bot.Builder.BotState+CachedBotState]} outerDc.Context.TurnState["ConversationState"] {Microsoft.Bot.Builder.BotState.CachedBotState}
Hash: "{}"
State: Count = 2
这是 QuickWatch 表达式,突出显示的值正是我所需要的。
当我尝试((Microsoft.Bot.Builder.BotState.CachedBotState)outerDc.Context.TurnState["ConversationState"]).State
在我的代码中使用表达式时,它似乎CachedBotState
不是命名空间/包的一部分。此外,这似乎是仍处于预览阶段的 nuget 包Microsoft.Bot.Builder.BotState.CachedBotState
的一部分。Microsoft.Bot.Builder.Core
我知道我可以将TurnState
对象作为附加参数从对话框传递OnTurnAsync
给我的对话框。但是,我想通过对话框的上下文访问它,当它显示它已经存在时。有没有办法做到这一点?
如果我可以详细说明,请告诉我。
解决方案
首先,CachedBotState
是一个内部实现细节,而不是你应该期望使用的东西。同样,您真的不应该深入研究TurnState
并期望使用其中不受您控制的值,因为它也只是机器人状态如何在回合范围内维护值的实现细节。我建议您放弃这种方法,因为最终整个实现可能会在下一个版本中发生变化(因为它是内部细节并且不受 semver 规则的约束),然后您的代码会因此而中断。
相反,您应该做的是IStatePropertyAccessor<TurnState>
在SomeDialog
创建它并将其添加到DialogSet
. 这使SomeDialog
您能够在给定的回合中读取/写入该特定属性,并且您的代码将改为如下所示:
public override Task<DialogTurnResult> ContinueDialogAsync(DialogContext outerDc, CancellationToken cancellationToken = default(CancellationToken))
{
// Access state via the property accessor rather than trying to access raw internals of bot state management
var turnState = await _turnStatePropertyAccessor.GetAsync(outerDc.Context);
outerDc.EndDialogAsync();
return base.ContinueDialogAsync(outerDc, cancellationToken);
}
推荐阅读
- reactjs - 在 Redux 中反应更新数组状态
- pagespeed-insights - PageSpeedInsights v5 根据 URL 返回不同的结果
- html - 有人可以帮我用 nth-child 伪类来定位我的容器 div 吗?
- html - Angular 6 - 如何根据条件禁用 div
- c++ - 如何在事件循环中运行 QClipboard,然后在 QClipboard 完成将某些内容复制到剪贴板后退出应用程序?
- c# - 文本框中的上一个条目在 Windows 窗体中被删除
- javascript - JavaScript 按嵌套对象降序排序数组
- amazon-web-services - c9 到 AWS 迁移
- git - 如何仅将对第三方存储库所做的更改存储在单独的存储库中?
- python - 在python中自动运行函数?