在对话框中使用Bot状态访问器

时间:2018-12-14 11:13:41

标签: c# botframework

我在Bot Framework上工作了几天,真是太新了。我一直在试图了解管理国家的情况,说实话我只是不明白。似乎最近的框架和建议已经发生了很大变化,似乎没有明确的建议或示例。

page说:

  

将信息保存为机器人状态。这将需要您设计   您的对话框可以访问机器人的状态属性访问器。

但是没有实现此目的的示例。

“瀑布”对话框之一的最后一步如下所示:

AddStep(async (stepContext, cancellationToken) =>
{
    var response = stepContext.Result as FoundChoice;
    stepContext.Values["maxPrice"] = response;

    return await stepContext.BeginDialogAsync(SearchDialog.Id, null, cancellationToken);
});

这基本上是一个新对话框的开始,我想通过将该对象从该对话框中收集的数据传递到SearchDialog中,或者最好将其保存到我的BotAccessors中,然后SearchDialog检索并使用它。

所有MS示例的瀑布步骤都定义为async类上的IBot方法。他们也不建议将bot对话框放在一起,使该示例变得毫无用处。

此外,似乎甚至Microsoft v4文档也已经过时,例如this doc,这仍然告诉我们使用不推荐使用的代码,例如:

options.State.Add(new ConversationState(storage));

不幸的是,目前看来,文档对这个主题的帮助比实际更令人困惑。管理此状态的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

看看在samples repocreating a basic bot中从Azure模板中设置基本漫游器的方式。

状态属性访问器在BasicBot类中声明:

private readonly IStatePropertyAccessor<GreetingState> _greetingStateAccessor;

然后将其分配到BasicBot constructor

_greetingStateAccessor = _userState.CreateProperty<GreetingState>(nameof(GreetingState));

然后它是passedGreetingDialog构造函数:

Dialogs.Add(new GreetingDialog(_greetingStateAccessor, loggerFactory));

然后将其分配给GreetingDialog类的属性:

UserProfileAccessor = userProfileStateAccessor ?? throw new ArgumentNullException(nameof(userProfileStateAccessor));

然后在整个GreetingDialog类中使用GetAsyncSetAsync方法在许多地方使用它。例如:

var greetingState = await UserProfileAccessor.GetAsync(stepContext.Context, () => null);

答案 1 :(得分:1)

“瀑布对话框”的最后两个步骤可能类似于以下内容:

public async Task<DialogTurnResult> AskForLocation(WaterfallStepContext sc, CancellationToken cancellationToken)
    {
        // the previous step asked for the Email so now bot is going to save it in botstate
        _state = await _accessor.GetAsync(sc.Context, () => new MyApplicationState());
        var email = _state.Email = (string)sc.Result;

        // this is not in the template because it is saving in a different manner
        // just being explicit about saving here
        await _accessor.SetAsync(sc.Context, _state);

        await sc.Context.SendActivityAsync("Got your email!");

        var prompt = new PromptOptions
        {
                Prompt = MessageFactory.Text($"Please specify location."),
        };

        return await stepContext.PromptAsync(locationPrompt, prompt);
    }

    public async Task<DialogTurnResult> FinishDialog(WaterfallStepContext sc, CancellationToken cancellationToken)
    {
        _state = await _accessor.GetAsync(sc.Context);
        _state.Location = (string)sc.Result;

        // save location this time
        await _accessor.SetAsync(sc.Context, _state);

        await sc.Context.SendActivityAsync("Got your location!");

        return await sc.EndDialogAsync();
    }

如果退出上面的对话框,并假设您实现了StateBotAccessors并且正在使用UserProfile属性,则可以通过以下方式检索它:

    var _state = await stateBotAccessors.UserState.UserProfileAccessor.GetAsync(context);

或者,如果您想从子对话框中传递它,则可以以:

结尾
    return await sc.EndDialogAsync(_state);