我有一个对话框,根据属性,数字要么提示用户,要么确认提示用户。然后,它检查瀑布stepcontext结果的类型是十进制还是布尔值。它按预期工作,但我认为它过于复杂并且容易出错。
有更好的方法吗?这是代码:
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);
}
答案 0 :(得分:0)
我建议将branching分为两个可能的子对话框。这些子对话框可以通过将价格通过stepContext.Values["price"]
传递给顶级对话框,而不是访问EndDialogAsync
。
我的其余答案都对您未明确询问的代码产生了影响。
由于您要提出建议,因此我应该提到Bot Framework示例很少扩展WaterfallDialog
。如果要创建自己的对话框类,从ComponentDialog
继承然后以WaterfallDialog
作为开始组件是更标准的选择,但是对于您而言,我不确定是否需要在所有。而且,如果您确实扩展了WaterfallDialog
,则在构造函数中具有相同的两个参数有点奇怪,因为您肯定不希望将任何步骤传递给它。为什么不这样做呢?
public LoanCalculator() : base(Id, null)