是否可以获取当前对话步骤名称?

Is it possible to get the current dialog step name?

我正在编写一个机器人,我想创建一个分步帮助系统。我设置了一个字典,允许每个对话框覆盖其中每个步骤的帮助文本:

public abstract class BaseDialog : ComponentDialog
{
    private static Dictionary<string, string> StepHelp = new Dictionary<string, string>();
    protected static void AddStepHelp(string function, string text)
    {
        StepHelp.Add(function, text);
    }
    private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
    {
        Activity helpMessage;
        string curStepName = ""; //???
        if (userText == "help" && StepHelp.ContainsKey(curStepName))
        {
            helpMessage = MessageFactory.Text(StepHelp[curStepName], StepHelp[curStepName], InputHints.ExpectingInput);
        }
        await innerDc.Context.SendActivityAsync(helpMessage, cancellationToken);
    }
}

然后我在 chidl 对话框中添加文本:

public class MyChildDialog: BaseDialog
{
    static MyChildDialog()
    {
        AddStepHelp(nameof(Step1), "Help text for step1");
    }
    public MyChildDialog()
    {
        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {
            Step1
        }));
        InitialDialogId = nameof(WaterfallDialog);
    }
    private async Task<DialogTurnResult> Step1(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {

    }
}

在上面的InterruptAsync函数中可以看到我调用了字典来获取基本对话框中的帮助信息,但是如何获取当前步骤名称呢?

您可以获得当前步骤 index 以及对话框名称,因此您应该能够从该信息创建一个唯一标识符(只要您没有像我一样为示例中的所有对话框命名 "waterfallDialog"!)。我正在使用节点,但我假设从您的 stepContext 获取数据是相似或相同的。

  • 对话框名称可以在 stepContext.stack[stepContext.stack.length-1].id 找到。
  • 可在 stepContext.stack[stepContext.stack.length-1].state.stepIndex 处找到步骤索引。

我不记得您是否可以在瀑布对话框中使用嵌套对话框。我知道您的 main/outer 上下文将包含整个堆栈,但我 认为 您将始终只有特定瀑布中的一个元素。也就是说,当前对话框应该是堆栈中的最后一个,因此在任何一种情况下都可以将其作为 stepContext.stack.length-1 访问。如果当前对话框位于元素 0,显然您可以直接访问它。

只要您的瀑布对话框名称是唯一的,您最终会得到诸如 waterfallDialog0、waterfallDialog1 等标识符,然后您可以将其映射到字典中以帮助文本。

我想到您可能正试图从瀑布对话框外部访问它。在那种情况下,您仍然应该能够从外部对话上下文中获取它。您可能必须使用递归函数来获取它,例如

getInnermostActiveDialog(dc) {
    var child = dc.child;

    return child ? this.getInnermostActiveDialog(child) : dc.activeDialog;
}

其中 dc 是您的外部对话上下文。我没有深入探讨,但你应该能够获得相同的 idstepIndex 值。

虽然如 billoverton 所述,获取步骤索引很容易,但获取步骤名称却很困难。 _steps field is private and so is the method that returns the step name 因此即使您的 class 派生自 WaterfallDialog,您也无法访问这些步骤。步骤名称仅通过遥测客户端公开,因此您可以考虑编写一个自定义遥测客户端,以某种方式将信息公开给您的机器人,但此时使用反射访问私有成员可能更容易。

由于您真的只想将步骤名称用作字典的键,因此只使用步骤索引是一个更好的选择。您可以使用 Dictionary<int, string>,但如果您打算为瀑布中的每个步骤提供帮助字符串,则使用 List<string> 是有意义的。