Botframework v4:瀑布stepcontext结果。如何简化?

时间:2019-02-19 03:33:38

标签: c# botframework

我有一个对话框,根据属性,数字要么提示用户,要么确认提示用户。然后,它检查瀑布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);
}

1 个答案:

答案 0 :(得分:0)

我建议将branching分为两个可能的子对话框。这些子对话框可以通过将价格通过stepContext.Values["price"]传递给顶级对话框,而不是访问EndDialogAsync

我的其余答案都对您未明确询问的代码产生了影响。

由于您要提出建议,因此我应该提到Bot Framework示例很少扩展WaterfallDialog。如果要创建自己的对话框类,从ComponentDialog继承然后以WaterfallDialog作为开始组件是更标准的选择,但是对于您而言,我不确定是否需要在所有。而且,如果您确实扩展了WaterfallDialog,则在构造函数中具有相同的两个参数有点奇怪,因为您肯定不希望将任何步骤传递给它。为什么不这样做呢?

public LoanCalculator() : base(Id, null)