EchoBot:如何控制从BotController到EchoBot的流程 [英] EchoBot: How does control flow from BotController to EchoBot
问题描述
我正在查看EchoBot示例并试图理解它.我看到BotController映射到api/messages和HttpPost,后者依次调用Adapter.ProcessAsync.但是,这如何转换为EchoBot.OnMessageActivityAsync调用?我试图设置一个断点并查看调用堆栈,但这无济于事(请参阅所附的屏幕截图).
我了解BotFrameworkHttpAdapter是通过依赖项注入来调用的.但是我不知道我们最终将如何进入EchoBot.
要真正找到答案,您必须深入源代码,所以我希望您拥有水肺潜水的装备,因为我们将继续深入
第1步
在 BotController.cs
内部文件中,我们有以下一行:
services.AddSingleton< IBotFrameworkHttpAdapter,BotFrameworkHttpAdapter>();
表示,每次我们要求使用 IBotFrameworkHttpAdapter
时,都提供 BotFrameworkHttpAdapter
的相同实例-本质上是静态变量,您可以阅读有关依赖项注入服务寿命的更多信息此处
第3步
在 Microsoft.Bot.Builder
包中,我们有 ProcessActivityAsync 的Builder/BotFrameworkAdapter.cs#L241"rel =" nofollow noreferrer>实现:
返回等待ProcessActivityAsync(claimsIdentity,activity,回调,cancellationToken).ConfigureAwait(false);
调用相同方法的重载,但是在我们从这里继续之前, callback
参数是之前通过的 bot.OnTurnAsync
参数./p>
第6步
ProcessActivityAsync
的重载也是此行:
using(var context = new TurnContext(this,activity))
创建上下文的位置,活动属性为 以及 所以我可以肯定地说,我们的 第8步 在 同一类上的 将用户的输入回显给他们,因此我们的旅程结束了. 关于第7步,Microsoft团队对于使用 除了在Visual Studio中,您还可以通过启用以下选项来调试一些库代码: 此外,如果您通过执行 您将能够检查Visual Studio本身中外部软件包的源代码. I am looking at the EchoBot sample and trying to understand it. I see that BotController is mapped to api/messages and HttpPost which in turn invokes Adapter.ProcessAsync. But how does this translate into EchoBot.OnMessageActivityAsync call? I tried to set up a breakpoint and see the call stack but that doesn't help ( see attached screenshot). I understand BotFrameworkHttpAdapter is invoked via dependency injection. But I don't know how we end up in EchoBot eventually. To find the answer to this you really have to dive into the source code, so I hope you've got your scuba diving gear because we're going deep. Step 1 Inside the which calls the Step 2 Inside the which says that every time we ask for an Step 3 Inside the which calls Step 5 Also inside the which calls an overload of the same method, but before we move on from here, the Step 6 The overload of where Step 7 Digging deeper still we find the implementation of the However, back in Step 6 we also had this line: where the context is created, and the activity property is initialised. This same But there are the following comment on the and inside the So I believe is it safe to say that our Step 8 In The Step 9 The which the Step 10 A custom implementation for where the user's input is echoed back to them, and thus our journey ends. Regarding Step 7, the Microsoft team are pretty active on SO for things tagged with As an aside in Visual Studio you can debug some library code by enabling the following option: Also if you enable navigation to decompiled sources (you will have to accept a legal notification popup) by doing this: You will be able to inspect the source code of external packages within Visual Studio itself. 这篇关于EchoBot:如何控制从BotController到EchoBot的流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!备注
部分中的内容:
...一旦控制到达管道的末尾,适配器将调用< paramref name ="callback"/>方法...
callback
方法正在执行,这意味着我们通过冒泡备份链来继续解析 callback
映射的功能,从而继续到( bot.OnTurnAsync
). BotController
中,我们将 IBot
的实例传递给 ProcessAsync
方法,而在 Startup
中,我们进行布线将所有对 IBot
的请求返回给 EchoBot
的实例,如下所示:
//将Bot创建为瞬态.在这种情况下,ASP控制器需要一个IBot.services.AddTransient< IBot,EchoBot>();
EchoBot
实现,用于 OnTurnAsync
方法,我将简化为:
开关(turnContext.Activity.Type){案例ActivityTypes.Message:return OnMessageActivityAsync(new DelegatingTurnContext< IMessageActivity>(turnContext),cancelledToken);//其他情况}
OnMessageActivityAsync
方法具有 botframework
标记的事情非常活跃,因此最好获取@mdrichardson或@tdurnford来澄清这里发生的事情.BotController.cs
file the following piece of code is called:await Adapter.ProcessAsync(Request, Response, Bot);
ProcessAsync
method on the IBotFrameworkHttpAdapter
interface.Startup.cs
file we have the following line:services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>();
IBotFrameworkHttpAdapter
, provide the same instance of BotFrameworkHttpAdapter
- essentially a static variable, you can read more about dependency injection service lifetimes here.Microsoft.Bot.Builder
package we have the implementation for the ProcessAsync
method, that can for our purposes be reduced to the following line:var invokeResponse = await ProcessActivityAsync(authHeader, activity, bot.OnTurnAsync, cancellationToken).ConfigureAwait(false);
ProcessActivityAsync
which is another function that lives in this library - the important part here is the bot.OnTurnAsync
parameter being passed in.Microsoft.Bot.Builder
package is the implementation for ProcessActivityAsync
:return await ProcessActivityAsync(claimsIdentity, activity, callback, cancellationToken).ConfigureAwait(false);
callback
parameter is the bot.OnTurnAsync
parameter that was passed through before.ProcessActivityAsync
is also implemented inside the Microsoft.Bot.Builder
package, and can be simplified to this line:await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);
callback
is bot.OnTurnAsync
.RunPipelineAsync
method inside of the Microsoft.Bot.Builder
package which is were things start to get a bit fuzzy... Theoretically we want to fall through to the else
block where the callback
(i.e. bot.OnTurnAsync
) is called:// 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);
}
}
using (var context = new TurnContext(this, activity))
context
is pass through to the RunPipelineAsync
call, which means that we will not fall through to the else block...RunPipelineAsync
method:/// <param name="callback">A callback method to run at the end of the pipeline.</param>
remarks
section:...Once control reaches the end of the pipeline, the adapter calls
the <paramref name="callback"/> method...
callback
method is being executed which means that we continue by bubbling back up the chain to resolve the function that callback
maps to (bot.OnTurnAsync
).BotController
we pass in an instance of IBot
to the ProcessAsync
method, and in Startup
we wire up all requests for an IBot
to return an instance of EchoBot
like so:// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, EchoBot>();
EchoBot
implementation inherits from the ActivityHandler
class:public class EchoBot : ActivityHandler
ActivityHandler
class provides a default implementation for the OnTurnAsync
method which I will simplify to:switch (turnContext.Activity.Type)
{
case ActivityTypes.Message:
return OnMessageActivityAsync(new DelegatingTurnContext<IMessageActivity>(turnContext), cancellationToken);
// Other cases
}
OnMessageActivityAsync
method on the same class that has an implementation that returns a completed task, i.e. is a no-op, however it is a virtual method - classes which inherit ActivityHandler
can provide their own implementation.OnMessageActivityAsync
is provided inside the EchoBot
class:protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync(MessageFactory.Text($"Echo: {turnContext.Activity.Text}"), cancellationToken);
}
botframework
so it might be best to get @mdrichardson or @tdurnford to clarify what happens here.