BotBuilder-Samples 'CreateNewConversationBot' 中的执行流程是什么?
What is the flow of execution in the BotBuilder-Samples' 'CreateNewConversationBot'?
我怀疑是 Ezequiel Jadib 的!
我正在尝试弄清楚上面的样本是如何组合在一起的,但我被打败了。
这是我的理解。我很抱歉 - 这里有很多。但我敢肯定,我并不是唯一一个试图了解 BotFramework SDK 处理传入消息的所有不同方式的人。
- 根容器已构建。添加了 DialogModule,以允许每个对话框实例的生命周期范围。 ResumptionCookie 在每个对话生命周期范围内相应地注册。然后添加 SurveyModule,它将 SurveyScheduler 建立为单例,将 CreateNewConversationDialog 建立为每个依赖项,并将 SurveyService 建立为每个对话框(DialogModule.LifetimeScopeTag。)SurveyService 和 SurveyScheduler 都是神秘的
.Keyed<ISurvey...>(FiberModule.Key_DoNotSerialize)
,我就是不确定,但是 认为 与这些对象的某些引用成员不可序列化这一事实有关?
所以,无论如何:每个 CreateNewConversationDialog 在实例化时都有自己的 SurveyService。
我们的 MessagesController 是一切的开始。它需要一个 ILifetimeScope 参数,该参数(正如我最近了解到的,谢谢 :) )由 Autofac 自动提供。问题:这个 ILifetimeScope 是根容器 - 即 SurveyTriggerer 中提到的同一个 ILifetimeScope,GlobalConfiguration.Configuration.DependencyResolver?
在 MessageController 的 Post 方法中,IPostToBot 在新的对话生命周期范围内解析,传入的消息发送到那里。这会自动找到上次使用的对话框吗?第一次肯定是找到了CreateNewConversationDialog,但是怎么会这样呢? DialogModule.BeginLifetimeScope() 的调用是否实际上隐式地将 IDialog 解析为 CreateNewConversationDialog,如在 SurveyModule 中注册的那样? IPostToBot 在哪里适合这个?我们没有使用 Conversation.SendAsync() 的原因是我们不知道我们当前是在 SurveyDialog 还是 CreateNewConversationDialog 中?
假设我们在 CreateNewConversationDialog 中,它只是循环接收到的每条消息,使用它自己的恢复 cookie 调用它自己的 SurveyService 的 QueueSurveyAsync(),将 cookie 添加到单例的并发队列中。
问题:为什么要有 SurveyService?为什么不在 CreateNewConversationDialog 本身中引用 SurveyScheduler 及其自己的 ResumptionCookie?
- SurveyScheduler 单例的 BackgroundWorkItem 不断轮询其队列,并使用 SurveyTriggerer 的静态 StartSurvey() 方法在堆栈上弹出一个 SurveyDialog,通过 ResumptionCookie 提取。 (这是比较容易理解的部分!)
感谢您的阅读,如有任何说明,我将不胜感激。
注意:我发现并非所有渠道都支持此示例,因此我很想模仿 'new direct conversation',只是采用 ContosoFlowers 中的方法,其中 returns 来自CheckoutController - 而是使用 Conversation.ResumeAsync() 并让调用对话框根据需要调用子对话框本身。这是一个疯狂的想法吗?
想到了一些东西(尽管有些答案可能会更长,因为有些主题太宽泛了)。
FiberModule.Key_DoNotSerialize
键主要用于指示BotBuilder在反序列化时从容器中而不是从序列化对象中恢复以对象类型为键的对象实例。 This thread 可能会有帮助。
- 它们不一样;控制器中的 ILifetimeScope 是一个
容器的子范围
GlobalConfiguration.Configuration.DependencyResolver。
- 简答:我们没有使用Conversation.SendAsync,因为这意味着手动创建对话框,我们希望使用 DI,因为对话框具有需要解决的依赖关系. 长答案:IPostToBot is the interface the contains the method to send a message from the user to the bot. There are tons of implementations of this interface in the BotBuilder library, and there is a chain of these registered in the AutoFac container. The incoming message flows through the chain until the last one (the PersistentDialogTask), which does a lot of black magic :), like using an ScoringEventLoop to dispatch the incoming activities to a scorable action; and if the scorable action does not match, it will go to the dialog system。您询问 :)。理解这一点的最佳方式;就是下载BotBuilder库的代码;将其连接到机器人并开始调试。
- 是的,可以按照您的建议进行简化。该示例基于 AlarmBot sample,因此我们在那里保留了很多片段。
- 是的。并在机器人和用户之间创建直接对话。如果频道支持直接对话(例如 Slack),如果您在多用户频道中与 Bot 交谈,它将在私人对话中启动调查。
示例的目的之一是展示如何根据永恒事件主动向用户发送消息。 Here 是一些关于主动消息的简单示例,我认为您会发现它们很有用。
我怀疑是 Ezequiel Jadib 的!
我正在尝试弄清楚上面的样本是如何组合在一起的,但我被打败了。
这是我的理解。我很抱歉 - 这里有很多。但我敢肯定,我并不是唯一一个试图了解 BotFramework SDK 处理传入消息的所有不同方式的人。
- 根容器已构建。添加了 DialogModule,以允许每个对话框实例的生命周期范围。 ResumptionCookie 在每个对话生命周期范围内相应地注册。然后添加 SurveyModule,它将 SurveyScheduler 建立为单例,将 CreateNewConversationDialog 建立为每个依赖项,并将 SurveyService 建立为每个对话框(DialogModule.LifetimeScopeTag。)SurveyService 和 SurveyScheduler 都是神秘的
.Keyed<ISurvey...>(FiberModule.Key_DoNotSerialize)
,我就是不确定,但是 认为 与这些对象的某些引用成员不可序列化这一事实有关?
所以,无论如何:每个 CreateNewConversationDialog 在实例化时都有自己的 SurveyService。
我们的 MessagesController 是一切的开始。它需要一个 ILifetimeScope 参数,该参数(正如我最近了解到的,谢谢 :) )由 Autofac 自动提供。问题:这个 ILifetimeScope 是根容器 - 即 SurveyTriggerer 中提到的同一个 ILifetimeScope,GlobalConfiguration.Configuration.DependencyResolver?
在 MessageController 的 Post 方法中,IPostToBot 在新的对话生命周期范围内解析,传入的消息发送到那里。这会自动找到上次使用的对话框吗?第一次肯定是找到了CreateNewConversationDialog,但是怎么会这样呢? DialogModule.BeginLifetimeScope() 的调用是否实际上隐式地将 IDialog 解析为 CreateNewConversationDialog,如在 SurveyModule 中注册的那样? IPostToBot 在哪里适合这个?我们没有使用 Conversation.SendAsync() 的原因是我们不知道我们当前是在 SurveyDialog 还是 CreateNewConversationDialog 中?
假设我们在 CreateNewConversationDialog 中,它只是循环接收到的每条消息,使用它自己的恢复 cookie 调用它自己的 SurveyService 的 QueueSurveyAsync(),将 cookie 添加到单例的并发队列中。
问题:为什么要有 SurveyService?为什么不在 CreateNewConversationDialog 本身中引用 SurveyScheduler 及其自己的 ResumptionCookie?
- SurveyScheduler 单例的 BackgroundWorkItem 不断轮询其队列,并使用 SurveyTriggerer 的静态 StartSurvey() 方法在堆栈上弹出一个 SurveyDialog,通过 ResumptionCookie 提取。 (这是比较容易理解的部分!)
感谢您的阅读,如有任何说明,我将不胜感激。
注意:我发现并非所有渠道都支持此示例,因此我很想模仿 'new direct conversation',只是采用 ContosoFlowers 中的方法,其中 returns 来自CheckoutController - 而是使用 Conversation.ResumeAsync() 并让调用对话框根据需要调用子对话框本身。这是一个疯狂的想法吗?
想到了一些东西(尽管有些答案可能会更长,因为有些主题太宽泛了)。
FiberModule.Key_DoNotSerialize
键主要用于指示BotBuilder在反序列化时从容器中而不是从序列化对象中恢复以对象类型为键的对象实例。 This thread 可能会有帮助。- 它们不一样;控制器中的 ILifetimeScope 是一个 容器的子范围 GlobalConfiguration.Configuration.DependencyResolver。
- 简答:我们没有使用Conversation.SendAsync,因为这意味着手动创建对话框,我们希望使用 DI,因为对话框具有需要解决的依赖关系. 长答案:IPostToBot is the interface the contains the method to send a message from the user to the bot. There are tons of implementations of this interface in the BotBuilder library, and there is a chain of these registered in the AutoFac container. The incoming message flows through the chain until the last one (the PersistentDialogTask), which does a lot of black magic :), like using an ScoringEventLoop to dispatch the incoming activities to a scorable action; and if the scorable action does not match, it will go to the dialog system。您询问 :)。理解这一点的最佳方式;就是下载BotBuilder库的代码;将其连接到机器人并开始调试。
- 是的,可以按照您的建议进行简化。该示例基于 AlarmBot sample,因此我们在那里保留了很多片段。
- 是的。并在机器人和用户之间创建直接对话。如果频道支持直接对话(例如 Slack),如果您在多用户频道中与 Bot 交谈,它将在私人对话中启动调查。
示例的目的之一是展示如何根据永恒事件主动向用户发送消息。 Here 是一些关于主动消息的简单示例,我认为您会发现它们很有用。