Embedding external dependencies in the Microsoft Bot Framework Dialog using Autofac

I am trying to pass the LuisDialog service from MessageController as follows:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity) ... await Conversation.SendAsync(activity, () => new ActionDialog(botService)); 

The botService service is injected into the MessageController using dependency injection.

When I start a bot conversation, I get an error message:

Type "ThetaBot.Services.BotService" in the assembly "ThetaBot.Services, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null" is not marked as serializable.

After looking at the solution, I can find: https://github.com/Microsoft/BotBuilder/issues/106

Now I understand your question. We have a similar problem with service objects that we want to create from a container, not from a serialized blob. This is how we register these objects in the container - we apply special processing during deserialization for all objects with the Key_DoNotSerialize key:

 builder .RegisterType<BotToUserQueue>() .Keyed<IBotToUser>(FiberModule.Key_DoNotSerialize) .AsSelf() .As<IBotToUser>() .SingleInstance(); 

However, I cannot find an example or documentation that details how to register my own dependencies in existing Bot Framework modules.

I also found https://github.com/Microsoft/BotBuilder/issues/252 , which indicates the ability to instantiate dialog boxes from a container.

I tried this sentence:

 Func<IDialog<object>> makeRoot = () => actionDialog; await Conversation.SendAsync(activity, makeRoot); 

Together with:

 builder .RegisterType<ActionDialog>() .Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize) .AsSelf() .As<ActionDialog>() .SingleInstance(); 

This does not work.

I also tried:

 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>()); } 

Together with the following in ApplicationModule:

  builder .RegisterType<ActionDialog>() .Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize) .AsSelf() .As<ActionDialog>() .SingleInstance(); 

This does not work, and I am facing the same problem.

If I just mark all services and their dependencies as serializable, I can get this to work without the need to use FiberModule.Key_DoNotSerialize.

The question is, what is the correct / preferred / recommended way to register and embed dependencies in Bot Framework dialogs?

+8
c # autofac botframework
source share
1 answer

In Global.asax.cs you can do the following to register your 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); 

In your controller, you can solve your main dialog box as:

 using (var scope = DialogModule.BeginLifetimeScope(Conversation.Container, activity)) { await Conversation.SendAsync(activity, () => scope.Resolve<IDialog<object>>()); } 
+7
source share

All Articles