c# - Botframework v4: waterfall stepcontext result. How to simplify?
问题描述
I have this dialog that either number prompt the user or confirm prompt the user depending on a property. It then check the type of waterfall stepcontext result if it is decimal or bool. It is working as intented but i think it is overcomplicated and prone to error.
Is there a better way to do this? Here is the code:
public class LoanCalculator : WaterfallDialog
{
public LoanCalculator(string dialogId, IEnumerable<WaterfallStep> steps = null)
: base(dialogId, steps)
{
AddStep(async (stepContext, cancellationToken) =>
{
// check if the property has a price
var userstate = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicUserStateAccessor.GetAsync(stepContext.Context);
// if zero, decimal prompt
if (userstate.PropertyPrice == 0)
{
return await stepContext.PromptAsync(
"numberPromptDecimal",
new PromptOptions
{
Prompt = MessageFactory.Text("Indicate price of property."),
RetryPrompt = MessageFactory.Text("Please enter a valid amount."),
});
}
else
{
// if not zero bool prompt confirm if user wants to change its value or not
return await stepContext.PromptAsync(
"confirmPrompt",
new PromptOptions
{
Prompt = MessageFactory.Text($"Property price is {userstate.PropertyPrice}. Is this correct?"),
});
}
});
AddStep(async (stepContext, cancellationToken) =>
{
var userstate = await (stepContext.Context.TurnState["BasicAccessors"] as BasicAccessors).BasicUserStateAccessor.GetAsync(stepContext.Context);
// if decimal prompt
if (stepContext.Result is decimal)
{
stepContext.Values["price"] = Convert.ToDecimal(stepContext.Result);
return await stepContext.NextAsync();
}
// if bool prompt
else if (stepContext.Result is bool)
{
// if user does not want to change value
if ((bool)stepContext.Result)
{
stepContext.Values["price"] = userstate.PropertyPrice;
return await stepContext.NextAsync();
}
// if user want to change value, make value zero and restart dialog
else
{
userstate.PropertyPrice = 0;
return await stepContext.ReplaceDialogAsync(Id);
}
}
else
{
// i dont know what to do with this so i just restart dialog
return await stepContext.ReplaceDialogAsync(Id);
}
});
AddStep(async (stepContext, cancellationToken) =>
{
// if stepcontext values is not equals to null
if (!stepContext.Values["price"].Equals(null))
{
return await stepContext.PromptAsync(
"numberPromptDecimal",
new PromptOptions
{
Prompt = MessageFactory.Text("Indicate amount of loan."),
RetryPrompt = MessageFactory.Text("Please enter a valid amount."),
});
}
else
{
// again dont know what to odo with this
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"oops"));
return await stepContext.ReplaceDialogAsync(Id);
}
});
AddStep(async (stepContext, cancellationToken) =>
{
// continue
});
}
public static string Id = "loanCalculator";
public static LoanCalculator Instance { get; } = new LoanCalculator(Id);
}
解决方案
我建议分成两个可能的子对话框。而不是访问stepContext.Values["price"]
,这些子对话框可以通过传递价格将价格返回到顶级对话框EndDialogAsync
。
我的其余答案会挑剔您没有特别询问的有关您的代码的事情。
由于您要求提供建议,因此我应该提到 Bot Framework 示例很少扩展WaterfallDialog
. 如果您想创建自己的对话框类,则继承自ComponentDialog
并具有 aWaterfallDialog
作为其起始组件会更加标准,但在您的情况下,我不确定您是否需要自定义对话框类。而且,如果您确实进行了扩展WaterfallDialog
,那么在构造函数中具有相同的两个参数会有点奇怪,因为您肯定不希望将任何步骤传递给它。为什么不这样做呢?
public LoanCalculator() : base(Id, null)
推荐阅读
- arrays - 如何迭代填充了文件和目录路径的文件以检查它们是什么
- objective-c - 如何使用 gtest 测试异步回调
- r - 如果单元只有一个观察值,则删除
- r - 在 R 中转换日期时间列时出现 NA 错误
- c# - 如何构建一个在主窗体打开时应该关闭的可移动启动窗体?
- swiftui - 如何在应用程序运行时保持数据持久性?
- javascript - 如何停止执行动态数量和类型的语句,直到一系列 ajax 调用完成?
- android - 更改默认的 react-native android 端口
- python - 仅当我想重命名或复制文件时,Python 突然找不到文件
- python - 在 Python 中构建列表时引用个人