在Botframework V4中扩展和链接对话框的正确方法?

时间:2019-02-25 11:59:40

标签: c# botframework

在我的OnTurnAsync中,我在单独的类中调用主对话框。并且主对话框也从其他类调用其他对话框,依此类推。这是分离和扩展Dialog的正确方法吗?我每个人都创建了单独的“组件对话框”。因为我的对话很漫长,并且在主Bot类中进行所有对话都很麻烦。

主对话框:

public class MainDialog : ComponentDialog
{
    private const string InitialId = "mainDialog";
    private const string ChoicePrompt = "choicePrompt";
    private const string DialogAId = "dialogAId";

    public MainDialog(string dialogId)
        : base(dialogId)
    {
        InitialDialogId = InitialId;

        WaterfallStep[] waterfallSteps = new WaterfallStep[]
         {
            FirstStepAsync,
            SecondStepAsync,
            ContinueStepAsync,
            ThirdStepAsync,
         };
        AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
        AddDialog(new ChoicePrompt(ChoicePrompt));
        AddDialog(new DialogA(DialogAId));
    }

    private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        return await stepContext.PromptAsync(
            ChoicePrompt,
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Here are your choices:"),
                Choices = new List<Choice>
                    {
                        new Choice
                        {
                            Value = "Open Dialog A",
                        },
                        new Choice
                        {
                            Value = "Open Dialog B",
                        },
                    },
                RetryPrompt = MessageFactory.Text($"Please choose one of the options."),
            });
    }

    private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        var response = (stepContext.Result as FoundChoice)?.Value.ToLower();

        if (response == "open dialog a")
        {
            return await stepContext.BeginDialogAsync(DialogAId, cancellationToken: cancellationToken);
        }

        if (response == "open dialog b")
        {
            // re-prompt not working btw
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Dialog B is not ready need to reprompt previous step."));
            await stepContext.RepromptDialogAsync();
        }

        return await stepContext.NextAsync();
    }

    private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        // what is the best way to end this?
        // return await stepContext.ReplaceDialogAsync(InitialId);
        return await stepContext.EndDialogAsync();
    }
}

对话框A代码:

 public class DialogA : ComponentDialog
{
    private const string InitialId = "dialogA";
    private const string ChoicePrompt = "choicePrompt";
    private const string DialogAchildId = "dialogA_childId";

    public DialogA(string dialogId)
        : base(dialogId)
    {
        InitialDialogId = InitialId;

        WaterfallStep[] waterfallSteps = new WaterfallStep[]
         {
            FirstStepAsync,
            SecondStepAsync,
            ContinueStepAsync,
            ThirdStepAsync,
         };
        AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
        AddDialog(new ChoicePrompt(ChoicePrompt));
        AddDialog(new DialogA_child(DialogAchildId));
    }

    private static async Task<DialogTurnResult> FirstStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        return await stepContext.PromptAsync(
            ChoicePrompt,
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Here are your choices:"),
                Choices = new List<Choice>
                    {
                        new Choice
                        {
                            Value = "Open Dialog A_Child",
                        },
                        new Choice
                        {
                            Value = "Open Dialog B_Child",
                        },
                    },
                RetryPrompt = MessageFactory.Text($"Please choose one of the options."),
            });
    }

    private static async Task<DialogTurnResult> SecondStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        var response = (stepContext.Result as FoundChoice)?.Value.ToLower();

        if (response == "open dialog a_child")
        {
            return await stepContext.BeginDialogAsync(DialogAchildId, cancellationToken: cancellationToken);
        }

        if (response == "open dialog b_child")
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Dialog B_child is not ready need to reprompt previous step."));
            await stepContext.RepromptDialogAsync();
        }

        return await stepContext.NextAsync();
    }

    private static async Task<DialogTurnResult> ContinueStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"should continue when dialog Achild closed."));
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($""));
        await stepContext.Context.SendActivityAsync(MessageFactory.Text($"will close dialog A."));
        return await stepContext.EndDialogAsync();
    }

    private static async Task<DialogTurnResult> ThirdStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        // what is the best way to end this?
        // return await stepContext.ReplaceDialogAsync(InitialId);
        return await stepContext.EndDialogAsync();
    }

1 个答案:

答案 0 :(得分:0)

除了your other issue中指出的问题外,是的,您正在正确地处理复杂的对话框。

通过精确地执行您的操作来管理复杂的对话框流要容易得多:拥有一个主要的对话框类,然后使用if语句分支到其他对话框。您可能还需要考虑使用switch语句,特别是如果您可能在两个以上的方向上分支。

参考文献

Advanced dialog flow-一般准则

Creating reusable dialogs-一般准则

What each method of stepContext does,与对话框相关-这样您就知道该调用什么来完成所需的操作

Prompt Validation Sample-必要时用于集成快速验证