EchoBot:如何控制从BotController到EchoBot的流程

时间:2019-07-03 21:24:24

标签: botframework

我正在查看EchoBot示例并试图理解它。我看到BotController映射到api / messages和HttpPost,后者依次调用Adapter.ProcessAsync。但是,这如何转换为EchoBot.OnMessageActivityAsync调用?我试图设置一个断点并查看调用堆栈,但这无济于事(请参阅所附的屏幕截图)。

enter image description here

我了解BotFrameworkHttpAdapter是通过依赖项注入来调用的。但我不知道我们最终将如何最终进入EchoBot。

1 个答案:

答案 0 :(得分:1)

要找到答案,您确实必须深入源代码,所以我希望您已经有了水肺潜水装备,因为我们正在深入研究。

第1步

BotController.cs file内,以下代码段被称为:

await Adapter.ProcessAsync(Request, Response, Bot);

ProcessAsync界面上调用IBotFrameworkHttpAdapter方法。

第2步

Startup.cs file内,我们有以下一行:

services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>();

这表示每次我们要求一个IBotFrameworkHttpAdapter时,都提供相同的BotFrameworkHttpAdapter实例-本质上是一个静态变量,您可以阅读有关依赖项注入服务寿命here的更多信息。 / p>

第3步

Microsoft.Bot.Builder包中,我们拥有ProcessAsync方法的implementation,出于我们的目的,可以将其简化为以下行:

var invokeResponse = await ProcessActivityAsync(authHeader, activity, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false);

调用ProcessActivityAsync是该库中的另一个函数-这里的重要部分是传入的bot.OnTurnAsync参数。

第5步

Microsoft.Bot.Builder包中还包含ProcessActivityAsync的{​​{3}}:

return await ProcessActivityAsync(claimsIdentity, activity, callback, cancellationToken).ConfigureAwait(false);

调用同一方法的重载,但是在我们从这里继续之前,callback参数是之前通过的bot.OnTurnAsync参数。

步骤6

ProcessActivityAsync的重载也位于Microsoft.Bot.Builder包中,implementation可以简化为以下行:

await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);

其中callbackbot.OnTurnAsync

第7步

更深入地研究,我们在RunPipelineAsync包中找到Microsoft.Bot.Builder方法的implemented,这是事情开始变得有点模糊的原因……从理论上讲,我们想要克服到else(即callback)被调用的bot.OnTurnAsync块:

// Call any registered Middleware Components looking for ReceiveActivityAsync()
if (turnContext.Activity != null)
{
    // Other code  
}
else
{
    // call back to caller on proactive case
    if (callback != null)
    {
        await callback(turnContext, cancellationToken).ConfigureAwait(false);
    }
}

但是,在第6步中,我们还有implementation行:

using (var context = new TurnContext(this, activity))

创建上下文的位置,活动属性为this。相同的context传递到RunPipelineAsync调用,这意味着我们不会陷入else块...

但是对RunPipelineAsync方法有以下评论:

/// <param name="callback">A callback method to run at the end of the pipeline.</param>

并在remarks部分中:

...Once control reaches the end of the pipeline, the adapter calls
the <paramref name="callback"/> method...

所以我可以肯定地说,我们的callback方法正在执行,这意味着我们通过冒泡备份链来继续解决callback映射到({{1 }。

第8步

bot.OnTurnAsync中,我们将BotController的一个实例传递给IBot方法,而在ProcessAsync中,我们将所有请求Startup的连接都返回IBot的实例,如下所示:

EchoBot

// Create the bot as a transient. In this case the ASP Controller is expecting an IBot. services.AddTransient<IBot, EchoBot>(); initialised继承自EchoBot类:

ActivityHandler

第9步

public class EchoBot : ActivityHandler 类为ActivityHandler方法提供了默认的implementation,我将简化为:

OnTurnAsync

在同一个类上的switch (turnContext.Activity.Type) { case ActivityTypes.Message: return OnMessageActivityAsync(new DelegatingTurnContext<IMessageActivity>(turnContext), cancellationToken); // Other cases } 方法具有一个implementation返回一个完成的任务,即是一个空操作,但是它是一个虚拟方法-继承{{1} }可以提供自己的实现。

步骤10

OnMessageActivityAsync类中提供了ActivityHandler的自定义implementation

OnMessageActivityAsync

将用户的输入回显给他们,因此我们的旅程结束了。


关于第7步,Microsoft团队非常积极地处理标有EchoBot的事情,因此最好获取@mdrichardson或@tdurnford来澄清这里发生的事情。


除了在Visual Studio中,您还可以通过启用以下选项来调试一些库代码:

  • 工具->选项->调试器
  • 取消选中“仅启用我的代码”

此外,如果您通过执行implementation来启用对反编译源的导航(您将必须接受合法通知弹出窗口):

  • 工具->选项->文本编辑器-> C#->高级
  • 选中“启用导航到反编译源”

您将能够检查Visual Studio本身中外部软件包的源代码。