为了账号安全,请及时绑定邮箱和手机立即绑定

Botframework v4:从没有计算器异常的子对话框调用父对话框

Botframework v4:从没有计算器异常的子对话框调用父对话框

C#
函数式编程 2022-11-21 16:30:15
据此我认为现在可以从子对话框调用父对话框。之前我不能这样做,因为它会导致堆栈溢出异常。我已经更新到 SDK 4.3 有谁知道如何实施这些更改吗?主对话框调用对话框 A。WaterfallStep[] waterfallSteps = new WaterfallStep[]     {        FirstStepAsync,        SecondStepAsync,        ThirdStepAsync,     };    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));    AddDialog(new DialogA(DialogAId));  return await stepContext.BeginDialogAsync(DialogAId, cancellationToken: cancellationToken);Dialog A 调用 Dialog Achild    WaterfallStep[] waterfallSteps = new WaterfallStep[]     {        FirstStepAsync,        SecondStepAsync,        ThirdStepAsync,     };    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));    AddDialog(new DialogAchild(DialogAchildId));   return await stepContext.BeginDialogAsync(DialogAchildId, cancellationToken: cancellationToken);Dialog Achild 调用MainDialog,但这会产生Stack 溢出异常。WaterfallStep[] waterfallSteps = new WaterfallStep[]     {        FirstStepAsync,        SecondStepAsync,        ThirdStepAsync,     };    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));    AddDialog(new MainDialog(MainDialogId));  return await stepContext.BeginDialogAsync(MainDialogId, cancellationToken: cancellationToken);
查看完整描述

1 回答

?
茅侃侃

TA贡献1842条经验 获得超21个赞

假设您在对话框的构造函数中添加对话框,那么您将产生一个无限循环,最终导致您所描述的堆栈溢出。


MainDialog --> DialogA --> DialogAchild --> MainDialog --> infinite loop

您提到的 PR 指的是一个稍微不同的问题。


解决此问题的一种方法是从构造函数中删除导致最终循环的 AddDialog 方法。相反,将调用移至 AddDialogA() 之类的方法,并仅在需要时调用它。


根据您的场景,您可以构建一个提供此类功能的基本对话框。


这是您可以在必要时AuthenticatedDialog添加的产品示例。OnboardingDialog请注意,入职对话框本身继承自 AuthenticatedDialog,当您不卸载AddDialog()呼叫时,这也会导致无限循环。


在基本对话框中抽象它很好,因为它为您提供了一些可以使用的 API。考虑将您的内容命名为 AddComponentDialog 或 UseComponentDialog。这样你就很好地表达了你的意图,潜在的读者一开始就知道你正在使用可重用的组件。


AuthenticatedDialog.cs


using Microsoft.Bot.Builder.Dialogs;

using Microsoft.Bot.Schema;

using Bot.Dialogs.Authentication;

using Bot.Dialogs.Main;

using Bot.Dialogs.Onboarding;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading;

using System.Threading.Tasks;


namespace Bot.Dialogs.Shared

{

    public class AuthenticatedDialog : EnterpriseDialog

    {

        private BotStateAccessors _accessors;

        private BotServices _botServices;


        public AuthenticatedDialog(BotServices botServices, string dialogId, BotStateAccessors accessors) : base(botServices, dialogId)

        {

            _accessors = accessors;

            _botServices = botServices;


            AddDialog(new AuthenticationDialog("", accessors));

        }


        protected async Task<DialogTurnResult> AskForOnboardingAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken, object stepResult = null)

        {

            return await stepContext.BeginDialogAsync(nameof(OnboardingDialog), stepResult, cancellationToken);

        }


        protected void AddOnboardingDialog()

        {

            AddDialog(new OnboardingDialog(_botServices,_accessors));

        }


    }

}

DialogA.cs


public class DialogA : AuthenticatedDialog

{


        public DialogA(BotServices botServices, BotStateAccessors accessors) : base(botServices, nameof(DialogA), accessors)

        {


            var preferencesDispatchSteps = new WaterfallStep[]

            {

                WaterfallStepA,

                WaterfallStepB

            };


            AddDialog(new FooDialog);

            AddOnboardingDialog();

        }

}


查看完整回答
反对 回复 2022-11-21
  • 1 回答
  • 0 关注
  • 56 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信