根据this,我认为现在可以从子对话框中调用父对话框了。在我不能这样做之前,因为它将导致堆栈溢出异常。我已经更新到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);
对话框A调用对话框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,但这会产生堆栈溢出异常。
WaterfallStep[] waterfallSteps = new WaterfallStep[]
{
FirstStepAsync,
SecondStepAsync,
ThirdStepAsync,
};
AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
AddDialog(new MainDialog(MainDialogId));
return await stepContext.BeginDialogAsync(MainDialogId, cancellationToken: cancellationToken);
答案 0 :(得分:0)
假设您要在对话框的构造函数中添加对话框,那么您将产生一个无限循环,最终导致所描述的堆栈溢出。
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();
}
}