从 DialogContext 获取 TurnState 数据
Getting TurnState data from DialogContext
我正在使用 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
,它包含我的机器人的状态数据,正如我在 immediate/watch window 中配置和看到的那样。
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
不是 namespace/package 的一部分。此外,Microsoft.Bot.Builder.BotState.CachedBotState
似乎是仍处于预览阶段的 Microsoft.Bot.Builder.Core
nuget 包的一部分。
我知道我可以将 TurnState
对象作为附加参数从 OnTurnAsync
传递到我的对话框。但是,当它显示它已经存在时,我想通过对话框的上下文访问它。有办法吗?
如果我可以详细说明,请告诉我。
首先,CachedBotState
是一个内部实现细节,不是您应该期望使用的东西。同样,您真的不应该深入研究 TurnState
并期望使用其中不受您控制的值,因为它也只是机器人状态如何在回合范围内维护值的实现细节.我建议您放弃这种方法,因为最终,整个实现可能会在下一个版本中发生变化(因为它是内部细节,不受 semver 规则的约束),然后您的代码就会因此中断。
相反,您应该做的是在创建 IStatePropertyAccessor<TurnState>
时将其传递给 SomeDialog
的构造函数并将其添加到 DialogSet
。这使 SomeDialog
能够 read/write 特定的 属性 对于给定的回合,您的代码将改为如下所示:
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);
}
我正在使用 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
,它包含我的机器人的状态数据,正如我在 immediate/watch window 中配置和看到的那样。
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
不是 namespace/package 的一部分。此外,Microsoft.Bot.Builder.BotState.CachedBotState
似乎是仍处于预览阶段的 Microsoft.Bot.Builder.Core
nuget 包的一部分。
我知道我可以将 TurnState
对象作为附加参数从 OnTurnAsync
传递到我的对话框。但是,当它显示它已经存在时,我想通过对话框的上下文访问它。有办法吗?
如果我可以详细说明,请告诉我。
首先,CachedBotState
是一个内部实现细节,不是您应该期望使用的东西。同样,您真的不应该深入研究 TurnState
并期望使用其中不受您控制的值,因为它也只是机器人状态如何在回合范围内维护值的实现细节.我建议您放弃这种方法,因为最终,整个实现可能会在下一个版本中发生变化(因为它是内部细节,不受 semver 规则的约束),然后您的代码就会因此中断。
相反,您应该做的是在创建 IStatePropertyAccessor<TurnState>
时将其传递给 SomeDialog
的构造函数并将其添加到 DialogSet
。这使 SomeDialog
能够 read/write 特定的 属性 对于给定的回合,您的代码将改为如下所示:
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);
}