I've been trying to pass a service to a LuisDialog from the MessagesController like so:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
...
await Conversation.SendAsync(activity, () => new ActionDialog(botService));
The botService is injected into the MessageController using dependency injection.
When I start a bot conversation I get an error:
Type 'ThetaBot.Services.BotService' in Assembly 'ThetaBot.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Looking around for a solution I can find: 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();
However I cannot find an example or documentation that details how to register your own dependencies into the existing Bot Framework modules.
I also found https://github.com/Microsoft/BotBuilder/issues/252 which indicates that it should be possible to instantiate the dialogs from the container.
I have tried this suggestion:
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 have 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 the ApplicationModule:
builder
.RegisterType<ActionDialog>()
.Keyed<ActionDialog>(FiberModule.Key_DoNotSerialize)
.AsSelf()
.As<ActionDialog>()
.SingleInstance();
This does not work and I encounter the same issue.
If I simply mark all the 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 inject dependencies into Bot Framework Dialogs?
ThetaBot.Services.BotServicetype in your Dialog. While that type is not marked as serializable, it cannot be used this way, independently on if it is injected or not. If you are good to make serializable all the services with their dependencies and store them with the Dialog state, you don't need to useFiberModule.Key_DoNotSerialize. In other case you can inject your services in some other place and use them from the Dialog without storing there. - Eugene Berdnikov