使用中断以优雅的方式取消当前对话框框架

问题描述

TL&DR

ComponentDialog类的

OnContinueDialogAsync方法,应允许中断对话框。但是,当我们有3个对话框时:MainDialog> SubDialogA> SubDialogAA,并且我们位于SubDialogAA内部,则中断命令将始终被MainDialog捕获。如何在SubDialogs(活动时)中捕获“较高”的中断,而又不从MainDialog中删除此逻辑?

更多详细信息

因此,根据本文: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-handle-user-interrupt?view=azure-bot-service-4.0&tabs=csharp我们应该使用包含中断处理的CancelAndHelpDialog类来处理中断,然后其他对话框应从该对话框派生。

下面是CancelAndHelpDialog

public class CancelAndHelpDialog : ComponentDialog
    {
        public InterruptionsHandleDialog (string id)
            : base(id)
        {
        }

        protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc,CancellationToken cancellationToken = default)
        {
            var result = await InterruptAsync(innerDc,cancellationToken);
            if (result != null)
            {
                return result;
            }

            return await base.OnContinueDialogAsync(innerDc,cancellationToken);
        }

        private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc,CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                    case "help":
                    case "?":
                        await innerDc.Context.SendActivityAsync("Help",cancellationToken: cancellationToken);
                        return new DialogTurnResult(DialogTurnStatus.Waiting);

                    case "cancel":
                        return await innerDc.CancelAllDialogsAsync(cancellationToken);
                }
            }
            return null;
        }
    }

我们有3个对话框,每个对话框都来自CancelAndHelpDialog: 主对话框> SubDialogA> SubDialogAA(>表示此对话框使用BeginDialogAsync调用另一个对话框)

现在,我已经在所有三个对话框中测试了“帮助”,并且可以正常工作。但这是从MainDialog调用的,因为MainDialog中断处理捕获了消息。

但是,“ cancel”仅在MainDialog中可以正常工作,因为它将始终被捕获并取消MainDialog。

当我们处于SubDialogA或SubDialogAA中时,允许取消当前对话框(使用CancelAllDialogs)的一种优雅方法是什么?

此外,如果所有内容仍然被MainDialog捕获,那么SubDialogA和SubDialogAA是否有必要从CancelAndHelpDialog派生出来?

解决方法

发现,如果对话框处于活动状态,则DialogContext(innerDc)的Child属性等于null。这仅允许对活动对话框执行中断:

public class CancelAndHelpDialog : ComponentDialog
    {
        public InterruptionsHandleDialog (string id)
            : base(id)
        {
        }

        protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc,CancellationToken cancellationToken = default)
        {
            var result = await InterruptAsync(innerDc,cancellationToken);
            if (result != null)
            {
                return result;
            }

            return await base.OnContinueDialogAsync(innerDc,cancellationToken);
        }

        private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc,CancellationToken cancellationToken)
        {
            if (innerDc.Context.Activity.Type == ActivityTypes.Message && innerDc.Child == null)
            {
                var text = innerDc.Context.Activity.Text.ToLowerInvariant();

                switch (text)
                {
                    case "help":
                    case "?":
                        await innerDc.Context.SendActivityAsync("Help",cancellationToken: cancellationToken);
                        return new DialogTurnResult(DialogTurnStatus.Waiting);

                    case "cancel":
                        return await innerDc.CancelAllDialogsAsync(cancellationToken);
                }
            }
            return null;
        }
    }

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...