waterfall 一旦形成,就应该逐步执行。但是,您可以有条件地形成waterfall steps。
这里的条件可以基于DialogId。
很难理解您到底想做什么,我已经为您准备了一个示例解决方案。希望您也尝试这样做。
请参考以下代码:
MainDialog.cs
namespace EchoBot.Dialogs
{
public class MainDialog : ComponentDialog
{
private readonly BotStateService _botStateService;
public MainDialog(BotStateService botStateService) : base(nameof(MainDialog))
{
_botStateService = botStateService;
InitializeWaterfallDialog();
}
private void InitializeWaterfallDialog()
{
var waterfallSteps = new WaterfallStep[]
{
InitialStepAsync,
FinalStepAsync
};
AddDialog(new SecondDialog($"{nameof(MainDialog)}.second", _botStateService));
AddDialog(new FirstDialog($"{nameof(MainDialog)}.first", _botStateService));
AddDialog(new FirstDialog($"{nameof(SecondDialog)}.firstFromSecond", _botStateService));
AddDialog(new WaterfallDialog($"{nameof(MainDialog)}.mainFlow", waterfallSteps));
InitialDialogId = $"{nameof(MainDialog)}.mainFlow";
}
private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
if (Regex.Match(stepContext.Context.Activity.Text.ToLower(), "hi").Success)
{
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.second", null, cancellationToken);
}
else
{
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.first", null, cancellationToken);
}
}
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.EndDialogAsync(null,cancellationToken);
}
} }
FirstDialog.cs
namespace EchoBot.Dialogs
{
public class FirstDialog : ComponentDialog
{
private readonly BotStateService _botStateService;
public FirstDialog(string dialogId, BotStateService botStateService) : base(dialogId)
{
_botStateService = botStateService ?? throw new ArgumentNullException(nameof(botStateService));
if (dialogId == $"{ nameof(MainDialog)}.first")
InitializeWaterfallDialog1();
else
InitializeWaterfallDialog2();
}
private void InitializeWaterfallDialog1()
{
var waterfallsteps = new WaterfallStep[]
{
GetAge,
GetCity,
FinalStepAsync
};
AddDialog(new WaterfallDialog($"{nameof(FirstDialog)}.mainFlow", waterfallsteps));
AddDialog(new NumberPrompt<int>($"{nameof(FirstDialog)}.age"));
AddDialog(new TextPrompt($"{nameof(FirstDialog)}.city"));
InitialDialogId = $"{nameof(FirstDialog)}.mainFlow";
}
private void InitializeWaterfallDialog2()
{
var waterfallsteps = new WaterfallStep[]
{
GetCity,
FinalStepAsync
};
AddDialog(new WaterfallDialog($"{nameof(FirstDialog)}.mainFlow", waterfallsteps));
AddDialog(new NumberPrompt<int>($"{nameof(FirstDialog)}.age"));
AddDialog(new TextPrompt($"{nameof(FirstDialog)}.city"));
InitialDialogId = $"{nameof(FirstDialog)}.mainFlow";
}
private async Task<DialogTurnResult> GetAge(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync($"{nameof(FirstDialog)}.age",
new PromptOptions
{
Prompt = MessageFactory.Text("Please enter your age."),
RetryPrompt = MessageFactory.Text("Please enter a valid age.")
}, cancellationToken);
}
private async Task<DialogTurnResult> GetCity(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync($"{nameof(FirstDialog)}.age",
new PromptOptions
{
Prompt = MessageFactory.Text("Please enter your city."),
RetryPrompt = MessageFactory.Text("Please enter a valid city.")
}, cancellationToken);
}
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.EndDialogAsync(null, cancellationToken);
}
}}
SecondDialog.cs
namespace EchoBot.Dialogs
{
public class SecondDialog : ComponentDialog
{
private readonly BotStateService _botStateService;
public SecondDialog(string dialogId, BotStateService botStateService) : base(dialogId)
{
_botStateService = botStateService ?? throw new ArgumentNullException(nameof(botStateService));
InitializeWaterfallDialog();
}
private void InitializeWaterfallDialog()
{
var waterfallSteps = new WaterfallStep[]
{
InitialStepAsync,
FinalStepAsync
};
AddDialog(new WaterfallDialog($"{nameof(SecondDialog)}.mainFlow", waterfallSteps));
AddDialog(new TextPrompt($"{nameof(SecondDialog)}.name"));
InitialDialogId = $"{nameof(SecondDialog)}.mainFlow";
}
private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync($"{nameof(SecondDialog)}.name",
new PromptOptions
{
Prompt = MessageFactory.Text("Please enter your Name.")
}, cancellationToken);
}
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
//Suppose you want to call First Dialog from here
return await stepContext.BeginDialogAsync($"{nameof(SecondDialog)}.firstFromSecond", null, cancellationToken);
}
}
}
在MainDialog.cs 中添加了一行 - AddDialog(new FirstDialog($"{nameof(SecondDialog)}.firstFromSecond", _botStateService));。对我来说效果很好。
图 1:当您从主对话框进入第二个对话框时,它会询问姓名,然后跳过第一个对话框的第一步(即年龄)并询问第二步,即。城市。
图 2:当您从主对话框直接进入第一个对话框时,它会询问年龄和城市,即。它没有跳过第一步。
希望这会有所帮助。有任何疑问请在 cmets 中提问!