首页 > 解决方案 > 从 Bot 类外部访问 BotState 变量

问题描述

在机器人类中,我们创建 ConversationState 和 UserState 对象,我们可以使用其访问器访问它们并在它们上创建属性,然后保存我们存储的数据。

但是,如果我想从 Bot 类调用的 Dialog 访问数据,我该怎么做呢?我知道我可以使用 BeginDialogAsync 选项参数通过 Context 传递对象。我怎么能通过其中两个而不是一个,以及如何让它们进入对话框类?

有没有办法访问 ConversationState 和 UserState 而不必将它们从一个对话框传递到另一个对话框?

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    await base.OnTurnAsync(turnContext, cancellationToken);

    // Save any state changes that might have occured during the turn.
    await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
}

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    Logger.LogInformation("Running dialog with Message Activity.");

    // Run the Dialog with the new message Activity.
    await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
}

在 CoreBot 示例的这个函数中,我们可以看到 ConversationState 和 UserState 被保存,但它们没有在其他任何地方修改,并且在第二个函数DialogState中,在子对话框中创建了一个属性,但我可以看到它也没有使用?有人可以解释为什么创建它们以及如何从刚刚调用的 Dialog 内部访问它们吗?

标签: c#azureasp.net-corebotframework

解决方案


您可以使用依赖注入。

 public class UserStateClass
 {
        public string name { get; set; }
 }

 public class YourDialog : ComponentDialog
 {
        private readonly IStatePropertyAccessor<UserStateClass> _userStateclassAccessor;

        public YourDialog(UserState userState)
            : base(nameof(YourDialog))
        {
            _userProfileAccessor = userState.CreateProperty<UserStateClass>("UserProfile");

            WaterfallStep[] waterfallSteps = new WaterfallStep[]
            {
                FirstStepAsync,
            };
            AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
        }

        private async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var userstate = await _userStateclassAccessor.GetAsync(stepContext.Context, () => new UserStateClass(), cancellationToken);

            userstate.name = "pepe";
            return await stepContext.EndDialogAsync();
        }
 }

推荐阅读