使用 Autofac 在 Microsoft Bot Framework 对话框中注入外部依赖项
Injecting external dependencies in Microsoft Bot Framework Dialog using Autofac
我一直在尝试将服务从 MessagesController 传递给 LuisDialog,如下所示:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
...
await Conversation.SendAsync(activity, () => new ActionDialog(botService));
使用依赖注入将 botService 注入到 MessageController 中。
当我开始机器人对话时出现错误:
程序集 'ThetaBot.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 中的类型 'ThetaBot.Services.BotService' 未标记为可序列化。
四处寻找我能找到的解决方案:
https://github.com/Microsoft/BotBuilder/issues/106
I understand your question better now. We have a similar issue with service objects that we want to instantiate from the container rather than from the serialized blob. Here is how we register those objects in the container - we apply special handling during deserialiation for all objects with the key Key_DoNotSerialize:
builder
.RegisterType<BotToUserQueue>()
.Keyed<IBotToUser>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<IBotToUser>()
.SingleInstance();
但是我找不到详细说明如何将您自己的依赖项注册到现有 Bot Framework 模块中的示例或文档。
我还发现 https://github.com/Microsoft/BotBuilder/issues/252 这表明应该可以从容器中实例化对话框。
我试过这个建议:
Func<IDialog<object>> makeRoot = () => actionDialog;
await Conversation.SendAsync(activity, makeRoot);
连同:
builder
.RegisterType<ActionDialog>()
.Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<ActionDialog>()
.SingleInstance();
这不起作用。
我也试过:
var builder = new ContainerBuilder();
builder.RegisterModule(new DialogModule_MakeRoot());
// My application module
builder.RegisterModule(new ApplicationModule());
using (var container = builder.Build())
using (var scope = DialogModule.BeginLifetimeScope(container, activity))
{
await Conversation.SendAsync(activity, () => scope.Resolve<ActionDialog>());
}
连同 ApplicationModule 中的以下内容:
builder
.RegisterType<ActionDialog>()
.Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<ActionDialog>()
.SingleInstance();
这不起作用,我遇到了同样的问题。
如果我简单地将所有服务及其依赖项标记为可序列化,则无需使用 FiberModule.Key_DoNotSerialize.
即可使其正常工作
问题是 - 注册依赖项并将依赖项注入 Bot Framework 对话框的正确/首选/推荐方法是什么?
在 Global.asax.cs 中,您可以执行以下操作来注册您的 services/dialogs:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<IntroDialog>()
.As<IDialog<object>>()
.InstancePerDependency();
builder.RegisterType<JobsMapper>()
.Keyed<IMapper<DocumentSearchResult, GenericSearchResult>>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces()
.SingleInstance();
builder.RegisterType<AzureSearchClient>()
.Keyed<ISearchClient>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces()
.SingleInstance();
builder.Update(Conversation.Container);
在您的控制器中,您可以将主对话框解析为:
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
await Conversation.SendAsync(activity, () => scope.Resolve<IDialog<object>>());
}
我一直在尝试将服务从 MessagesController 传递给 LuisDialog,如下所示:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
...
await Conversation.SendAsync(activity, () => new ActionDialog(botService));
使用依赖注入将 botService 注入到 MessageController 中。
当我开始机器人对话时出现错误:
程序集 'ThetaBot.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 中的类型 'ThetaBot.Services.BotService' 未标记为可序列化。
四处寻找我能找到的解决方案: https://github.com/Microsoft/BotBuilder/issues/106
I understand your question better now. We have a similar issue with service objects that we want to instantiate from the container rather than from the serialized blob. Here is how we register those objects in the container - we apply special handling during deserialiation for all objects with the key Key_DoNotSerialize:
builder
.RegisterType<BotToUserQueue>()
.Keyed<IBotToUser>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<IBotToUser>()
.SingleInstance();
但是我找不到详细说明如何将您自己的依赖项注册到现有 Bot Framework 模块中的示例或文档。
我还发现 https://github.com/Microsoft/BotBuilder/issues/252 这表明应该可以从容器中实例化对话框。
我试过这个建议:
Func<IDialog<object>> makeRoot = () => actionDialog;
await Conversation.SendAsync(activity, makeRoot);
连同:
builder
.RegisterType<ActionDialog>()
.Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<ActionDialog>()
.SingleInstance();
这不起作用。
我也试过:
var builder = new ContainerBuilder();
builder.RegisterModule(new DialogModule_MakeRoot());
// My application module
builder.RegisterModule(new ApplicationModule());
using (var container = builder.Build())
using (var scope = DialogModule.BeginLifetimeScope(container, activity))
{
await Conversation.SendAsync(activity, () => scope.Resolve<ActionDialog>());
}
连同 ApplicationModule 中的以下内容:
builder
.RegisterType<ActionDialog>()
.Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<ActionDialog>()
.SingleInstance();
这不起作用,我遇到了同样的问题。
如果我简单地将所有服务及其依赖项标记为可序列化,则无需使用 FiberModule.Key_DoNotSerialize.
即可使其正常工作问题是 - 注册依赖项并将依赖项注入 Bot Framework 对话框的正确/首选/推荐方法是什么?
在 Global.asax.cs 中,您可以执行以下操作来注册您的 services/dialogs:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<IntroDialog>()
.As<IDialog<object>>()
.InstancePerDependency();
builder.RegisterType<JobsMapper>()
.Keyed<IMapper<DocumentSearchResult, GenericSearchResult>>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces()
.SingleInstance();
builder.RegisterType<AzureSearchClient>()
.Keyed<ISearchClient>(FiberModule.Key_DoNotSerialize)
.AsImplementedInterfaces()
.SingleInstance();
builder.Update(Conversation.Container);
在您的控制器中,您可以将主对话框解析为:
using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity))
{
await Conversation.SendAsync(activity, () => scope.Resolve<IDialog<object>>());
}