在第一步Bot Framework v4之后,将访问器传递给WaterfallDialog导致错误

时间:2019-01-07 19:30:49

标签: c# .net dialog botframework state-management

当我将BotAccessors从主对话框传递到另一个对话框时,我遇到了问题。我之所以要发送访问器,是因为我需要从任何对话框访问然后保存UserProfile中的状态。 这是我通过的方式:

await dialogContext.BeginDialogAsync(SiteReviewDialog.id, _accessors, cancellationToken: cancellationToken);

SiteReviewDialog的第一步运行良好,并提示用户,但在进入第二步之前它就出错了(断点不会命中)。 我尝试删除accessors中所有对SiteReviewDialog的引用,看来解决此问题的唯一方法是完全不传递accessors。如果我通过accessors,我得到的错误是:http://freetexthost.com/sdgdilpyxv

从错误起,第232行在我的OnTurnAsync内:

var dialogContext = await _dialogs.CreateContextAsync(turnContext, cancellationToken);

我试图从第一个SiteReviewDialog开始遵循AddStep(async (stepContext, cancellationToken)中的代码执行,它逐行退出,然后命中OnTurnAsync并到达第232行,然后出现错误。有人有建议吗?

1 个答案:

答案 0 :(得分:1)

要说明首先发生的情况:传递_accessors的参数保留给Dialog的“选项”对象。这类似于对话框的行为设置。例如,对于提示,它始终是PromptOptions子类。这些选项对象在对话框的执行生命周期内被序列化并存储在堆栈中,因此之所以会通过_accessors导致异常是因为它包含不可序列化的类型。因此,长话短说,您不想以这种方式传递访问者。

访问器实际上是单例,您需要做的是将它们通过对话框的构造函数链传递。因此,您可以将IStatePropertyAccessor<T>(如果您决定遵循该模式,则使用“ accessors”类)作为SiteReviewDialog构造函数,然后确保将其传递给它通过其创建的任何子对话框构造函数。注意:对话框本身也应该真正创建为单例。

从那里开始,只需要使用访问器就可以了,因为您总是给它一个ITurnContext来从中加载数据,并且单例实例使用特定于该上下文的标识符来确保正确数据已加载。