Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Botframework v4:如何简化这个瀑布式对话框?_C#_Botframework - Fatal编程技术网

C# Botframework v4:如何简化这个瀑布式对话框?

C# Botframework v4:如何简化这个瀑布式对话框?,c#,botframework,C#,Botframework,我有这个代码,但我认为它过于复杂,可以简化。 如果用户键入“back”而不重新启动整个对话框,是否有方法返回到spefici瀑布步骤?我是新手,很难找到关于BotFrameworkV4的指南或在线课程,因为它是新的。任何帮助都将不胜感激,谢谢 public GetNameAndAgeDialog(string dialogId, IEnumerable<WaterfallStep> steps = null) : base(dialogId, steps) {

我有这个代码,但我认为它过于复杂,可以简化。 如果用户键入“back”而不重新启动整个对话框,是否有方法返回到spefici瀑布步骤?我是新手,很难找到关于BotFrameworkV4的指南或在线课程,因为它是新的。任何帮助都将不胜感激,谢谢

  public GetNameAndAgeDialog(string dialogId, IEnumerable<WaterfallStep> steps = null) : base(dialogId, steps)
    {
        var name = "";
        var age = "";

        AddStep(async (stepContext, cancellationToken) =>
        {
            return await stepContext.PromptAsync("textPrompt",
                new PromptOptions
                {
                    Prompt = stepContext.Context.Activity.CreateReply("What's your name?")
                });
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            name = stepContext.Result.ToString();

            return await stepContext.PromptAsync("numberPrompt",
                new PromptOptions
                {
                    Prompt = stepContext.Context.Activity.CreateReply($"Hi {name}, How old are you ?")
                });
        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            age= stepContext.Result.ToString();

            return await stepContext.PromptAsync("confirmPrompt",
              new PromptOptions
              {
                  Prompt = stepContext.Context.Activity.CreateReply($"Got it you're {name}, age {age}. {Environment.NewLine}Is this correct?"),
                  Choices = new[] {new Choice {Value = "Yes"},
                                   new Choice {Value = "No"},
                   }.ToList()
              });

        });

        AddStep(async (stepContext, cancellationToken) =>
        {
            var result = (stepContext.Result as FoundChoice).Value;

            if(result == "Yes" || result == "yes" || result == "Yeah" || result == "Correct" || result == "correct")
            {
                var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
                state.Name = name;
                state.Age = int.Parse(age);

                return await stepContext.BeginDialogAsync(MainDialog.Id, cancellationToken);
            }
            else
            {
                //restart the dialog
                return await stepContext.ReplaceDialogAsync(GetNameAndAgeDialog.Id);
            }

        });

    }

    public static string Id => "GetNameAndAgeDialog";
    public static GetNameAndAgeDialog Instance { get; } = new GetNameAndAgeDialog(Id);
}
public GetNameAndAgeDialog(string dialogId,IEnumerable steps=null):base(dialogId,steps)
{
var name=“”;
var age=“”;
AddStep(异步(stepContext,cancellationToken)=>
{
返回wait wait stepContext.PromptAsync(“textPrompt”,
新提示
{
Prompt=stepContext.Context.Activity.CreateReply(“您叫什么名字?”)
});
});
AddStep(异步(stepContext,cancellationToken)=>
{
name=stepContext.Result.ToString();
返回wait wait stepContext.PromptAsync(“numbercompt”,
新提示
{
Prompt=stepContext.Context.Activity.CreateReply($“你好{name},你多大了?”)
});
});
AddStep(异步(stepContext,cancellationToken)=>
{
age=stepContext.Result.ToString();
返回wait wait stepContext.PromptAsync(“confirmport”,
新提示
{
Prompt=stepContext.Context.Activity.CreateReply($“明白了,您是{name},age{age}.{Environment.NewLine}这对吗?”),
Choices=new[]{new Choice{Value=“Yes”},
新选项{Value=“No”},
}托利斯先生()
});
});
AddStep(异步(stepContext,cancellationToken)=>
{
var result=(stepContext.result作为FoundChoice).Value;
如果(结果==“是”| |结果==“是”| |结果==“是”| |结果==“正确”| |结果==“正确”)
{
var state=await(stepContext.Context.TurnState[“FPBotAccessors”]作为FPBotAccessors)。FPBotStateAccessor.GetAsync(stepContext.Context);
state.Name=名称;
state.Age=int.Parse(Age);
返回wait wait stepContext.BeginDialogAsync(MainDialog.Id,cancellationToken);
}
其他的
{
//重新启动对话框
返回wait-stepContext.ReplaceDialogAsync(GetNameAndAgeDialog.Id);
}
});
}
公共静态字符串Id=>“GetNameAndAgeDialog”;
公共静态GetNameAndAgeDialog实例{get;}=new GetNameAndAgeDialog(Id);
}
这是我的访问者代码:

    public class FPBotAccessors
{
    public FPBotAccessors(ConversationState conversationState)
    {
        ConversationState = conversationState ?? throw new ArgumentNullException(nameof(conversationState));
    }

    public static string FPBotAccessorName { get; } = $"{nameof(FPBotAccessors)}.FPBotState";
    public IStatePropertyAccessor<FPBotState> FPBotStateAccessor { get; internal set; }

    public static string DialogStateAccessorName { get; } = $"{nameof(FPBotAccessors)}.DialogState";
    public IStatePropertyAccessor<DialogState> DialogStateAccessor { get; internal set; }
    public ConversationState ConversationState { get; }
    //
    public static string ConversationFlowName { get; } = "ConversationFlow";
    public IStatePropertyAccessor<ConversationFlow> ConversationFlowAccessor { get; set; }
}
公共类访问器
{
公共FPBOT访问器(会话状态会话状态)
{
ConversationState=ConversationState??抛出新的ArgumentNullException(nameof(ConversationState));
}
公共静态字符串FPBotAccessorName{get;}=$“{nameof(FPBotAccessors)}.FPBotState”;
公共IStatePropertyAccessor FPBotStateAccessor{get;internal set;}
公共静态字符串DialogStateAccessorName{get;}=$“{nameof(FPBotAccessors)}.DialogState”;
公共IStatePropertyAccessor对话框StateAccessor{get;internal set;}
公共会话状态会话状态{get;}
//
公共静态字符串ConversationFlowName{get;}=“ConversationFlow”;
公共IStatePropertyAccessor会话流访问器{get;set;}
}

因此,您的代码存在一些问题,您可以采取一些措施来改进代码

对话框中的状态 首先,让我们从这样一个事实开始:在构造函数中关闭局部变量,并从表示步骤的闭包中访问这些变量。这种方法现在“有效”,但最终是有缺陷的。初始缺陷是不同的,这取决于您在实例化
GetNameAndAgeDialog
对话框时采用的方法

如果您将其作为单例使用,这意味着用户和您的bot之间的所有活动对话都将通过该实例进行,并且您将遇到并发问题,即两个用户同时与bot对话时,将其值存储到同一内存(这些变量)中,并踩在彼此的数据上

也有可能,根据您所遵循的示例,您会在每一轮中实例化
GetNameAndAgeDialog
。这意味着在每次对话中,这些变量都会被初始化为空字符串,这样您就无法跟踪原始值

最终,无论使用何种实例,无论何时扩展,这种方法最终都是有缺陷的,因为充其量您的状态将被绑定到单个服务器实例,并且如果一轮对话发生在
ServerA
上,而下一轮对话发生在
ServerM
上,那么
ServerM
将没有上一轮

很明显,你需要用某种适当的状态管理机制来存储它们。您显然对使用
BotState
(无论是对话还是用户范围)有些熟悉,因为您已经在使用状态属性访问器,但是在收集过程结束之前,将在多回合提示中收集的值存储到更永久的地方可能还为时过早。幸运的是,对话框本身存储在状态中,当您为
DialogState
设置状态属性访问器时,您可能已经找到了状态,因此提供了一种临时持久性机制,该机制与对话框堆栈上每个对话框的生存期相关联。使用这种状态并不明显,也没有很好的文档记录,但是
waterwalldialog
实际上更进一步,通过
public GetNameAndAgeDialog(string dialogId, IEnumerable<WaterfallStep> steps = null) : base(dialogId, steps)
{
    AddStep(async (stepContext, cancellationToken) =>
    {
        return await stepContext.PromptAsync("textPrompt",
            new PromptOptions
            {
                Prompt = MessageFactory.Text("What's your name?"),
            },
            cancellationToken: cancellationToken);
    });

    AddStep(async (stepContext, cancellationToken) =>
    {
        var name = (string)stepContext.Result;

        stepContext.Values["name"] = name;

        return await stepContext.PromptAsync("numberPrompt",
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Hi {name}, How old are you ?"),
            },
            cancellationToken: cancellationToken);
    });

    AddStep(async (stepContext, cancellationToken) =>
    {
        var age = (int)stepContext.Result;

        stepContext.Values["age"] = age;

        return await stepContext.PromptAsync("confirmPrompt",
            new PromptOptions
            {
                Prompt = MessageFactory.Text($"Got it you're {name}, age {age}.{Environment.NewLine}Is this correct?"),
            },
            cancellationToken: cancellationToken);

    });

    AddStep(async (stepContext, cancellationToken) =>
    {
        var result = (bool)stepContext.Result;

        if(result)
        {
            var state = await (stepContext.Context.TurnState["FPBotAccessors"] as FPBotAccessors).FPBotStateAccessor.GetAsync(stepContext.Context);
            state.Name = stepContext.Values["name"] as string;
            state.Age = stepContext.Values["age"] as int;

            return await stepContext.ReplaceDialogAsync(MainDialog.Id, cancellationToken: cancellationToken);
        }
        else
        {
            //restart the dialog
            return await stepContext.ReplaceDialogAsync(GetNameAndAgeDialog.Id, cancellationToken: cancellationToken);
        }
    });
}