我正在查看EchoBot示例并试图理解它。我看到BotController映射到api / messages和HttpPost,后者依次调用Adapter.ProcessAsync。但是,这如何转换为EchoBot.OnMessageActivityAsync调用?我试图设置一个断点并查看调用堆栈,但这无济于事(请参阅所附的屏幕截图)。
我了解BotFrameworkHttpAdapter是通过依赖项注入来调用的。但我不知道我们最终将如何最终进入EchoBot。
答案 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);
其中callback
是bot.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来启用对反编译源的导航(您将必须接受合法通知弹出窗口):
您将能够检查Visual Studio本身中外部软件包的源代码。