我们之前有三篇文章已经讲述了的基本使用和基本的原理以及应用场景,我们这一篇看看如何利用实现循环任务。阅读本章前,需要使用如下的文章先创建好项目:
请根据上述三篇文章一步一步完成,就有了一个实现了,并且实现了主线任务以及分支任务的代码了。
什么是循环任务?例如在聊天的会话中,我们需要对某些场景进行分页,显示更多的数据,或者需要用户重复的确认某一件合同,收集不同的信息,等等都可以实现为一个循环任务。我们本例继续延续之前的场景,当用户年龄大于35岁,询问他是否会购买保险,如果用户选择了购买保险,那么我们需要给用户看一个3页的保险说明书,案例中使用循环任务实现了从第一页保险说明循环到最后一页退出,或者用户选择特定的按钮退出循环。
开始之前一定要按照上面的三遍文章一步一步的创建好项目, 我们现在继续实现循环任务。
开始代码
在已有的项目中,我们已经有一个 - , 为了完成循环任务我们需要另外一个新的, 我们可以命名为:, 专门用于处理保险的循环任务。
先给代码,再解释:
:
usingMicrosoft.Bot.Builder.Dialogs;
usingMicrosoft.Bot.Builder;
usingMicrosoft.Bot.Builder.Dialogs.Choices;
namespaceCoreBot.Dialogs;
publicclassInsuranceDialog:ComponentDialog
{
publicInsuranceDialog() :base(nameof(InsuranceDialog))
{
AddDialog(newChoicePrompt(nameof(ChoicePrompt)));
AddDialog(newWaterfallDialog(
nameof(WaterfallDialog),
newWaterfallStep[]
{
ReadInsuranceDetail,
CheckReadPage
}
));
InitialDialogId=nameof(WaterfallDialog);
}
publicasyncTaskReadInsuranceDetail(WaterfallStepContextwaterfallStepContext,CancellationTokencancellationToken)
{
waterfallStepContext.Values["PageOptions"]=null;
varpageOptions=waterfallStepContext.OptionsasPageOptions??newPageOptions()
{
TotalPage=3,
CurrentPage=1
};
varreply=waterfallStepContext.Context.Activity.CreateReply();
reply.Text=$"保险协议,您当前阅读的在页";
awaitwaterfallStepContext.Context.SendActivityAsync(reply,cancellationToken);
varoptions=newPromptOptions()
{
Prompt=MessageFactory.Text("请阅读保险协议"),
RetryPrompt=MessageFactory.Text("请仔细阅读保险协议"),
Choices=GetChoices(),
};
waterfallStepContext.Values["PageOptions"]=pageOptions;
returnawaitwaterfallStepContext.PromptAsync(nameof(ChoicePrompt), options, cancellationToken);
}
publicasyncTaskCheckReadPage(WaterfallStepContextwaterfallStepContext,CancellationTokencancellationToken)
{
varcheckValue=((FoundChoice)waterfallStepContext.Result).Value;
if( checkValue.Equals("下页"))
{
PageOptionspageOptions=(PageOptions)waterfallStepContext.Values["PageOptions"];
if(pageOptions.TotalPage
{
//直接退出了.
varreply=waterfallStepContext.Context.Activity.CreateReply();
reply.Text="已经浏览完所有搜索结果。";
awaitwaterfallStepContext.Context.SendActivityAsync(reply, cancellationToken);
returnawaitwaterfallStepContext.EndDialogAsync(null, cancellationToken);
}
else
{
pageOptions.CurrentPage+=1;
returnawaitwaterfallStepContext.ReplaceDialogAsync(nameof(InsuranceDialog), pageOptions, cancellationToken);
}
}
else
{
varreply=waterfallStepContext.Context.Activity.CreateReply();
reply.Text="退出浏览搜索结果。";
awaitwaterfallStepContext.Context.SendActivityAsync(reply, cancellationToken);
returnawaitwaterfallStepContext.EndDialogAsync(null, cancellationToken);
}
}
privateIListGetChoices()
{
varcardOptions=newList()
{
newChoice() { Value="下页", Synonyms=newList() {"下一页"} },
newChoice() { Value="退出", Synonyms=newList() {"退出"} },
};
returncardOptions;
}
}
代码比较长,但是核心的价值主要是两个:
通过数组在不同的之间传递状态和状态数据。
通过方法来显式的调用需要的, 注意根据来调用,也就是在构造函数里输入的。
其他的更改
更改一下`MainDialog.cs':
更改构造函数,添加新的:
publicclassMainDialog:ComponentDialog
{
publicMainDialog() :base(nameof(MainDialog))
{
AddDialog(newTextPrompt("get-nick-name", NickNameNotNull));
AddDialog(newNumberPrompt("get-age"));
AddDialog(newChoicePrompt(nameof(ChoicePrompt)));
AddDialog(newInsuranceDialog());
AddDialog(newWaterfallDialog(nameof(WaterfallDialog),newWaterfallStep[]{
GetNickName,
GetAge,
SetAgeForHealth,
ShowNickNameAndAge,
}));
InitialDialogId=nameof(WaterfallDialog);
}
更改方法:
publicasyncTaskShowNickNameAndAge(WaterfallStepContextwaterfallStepContext,CancellationTokencancellationToken)
{
varAge=Convert.ToInt32(waterfallStepContext.Values["Age"]);
varNickName=waterfallStepContext.Values["NickName"];
varreply=waterfallStepContext.Context.Activity.CreateReply();
reply.Text=$"您好,您输入的昵称是:, 您输入的年龄是:";
if(Age>35)
{
varchoice=((FoundChoice)waterfallStepContext.Result).Value;
if(choice.Equals("购买保险"))
{
reply.Text="您已经购买了保险。";
returnawaitwaterfallStepContext.BeginDialogAsync(nameof(InsuranceDialog),null, cancellationToken);
}
}
awaitwaterfallStepContext.Context.SendActivityAsync(reply, cancellationToken);
returnawaitwaterfallStepContext.EndDialogAsync(null, cancellationToken);
}
主要是更改这一句:, 开始调用下一个, 这样我们就完成了整个的代码更改。
您可以尝试运行一下,查看结果:
这里有一个有趣的问题,给大家留作业,大家会发现,我们在循环了之后,就直接退出了,该怎么办让循环结束后,怎么回到之前的调用方法呢?
答案很容易,期望大家也能快速的想到,这样对于的理解也就会更加深入一步了。
领取专属 10元无门槛券
私享最新 技术干货