Browsed by
Tag: IoC

IoC in the Bot Framework

IoC in the Bot Framework

My first post is going to surface some information that is pretty difficult to find and doesn’t exist all in one place. Hopefully it will be of benefit other people using the Bot Framework.

If you’ve used the Microsoft Bot Framework before, you’ll know that even though it’s well ahead of any other bot frameworks in terms of functionality, writing your bot code can be a bit tricky. There’s a bunch of hoops to jump through and the documentation isn’t always the most helpful.

One of the things that I’ve struggled with is that everything needs to be serializable. In theory this doesn’t sound like a problem until you want to separate your conversational bot code and your “service” code (i.e. calls to external APIs or data sources).

Solution 1: Service locator

The first solution that I came across was using a static factory for getting my dependencies.

This simple solution solved the problem with small amounts of code. Unfortunately it’s an implementation of the widely know anti-pattern; the Service Locator.

For all of the usual reasons, the static factory wasn’t great. There was no way to mock the services in the factory as they were just new’d up at run time, It definitely violates the Dependency Injection principle of SOLID and as I add more dependencies it will just grow and grow unless split into even more static factories!

Solution 2: Slightly improved service locator

The next evolution from here was to use an IoC container to create all of the dependencies and then to use the static factory to access the container and get the required services for the dialog class.

Slightly better than before. I can now set up my container in my tests and have the factory return mocked interfaces where appropriate. For quite some time, this is pattern that I used. I knew it wasn’t the best and I knew that it was still just a service locator.

Solution 3: Constructor injection via magic

I spent some time looking around for solutions and then finally in the depths of the BotBuilder GitHub issues I found these two issues raised by the same user:

https://github.com/Microsoft/BotBuilder/issues/106
https://github.com/Microsoft/BotBuilder/issues/938

Will gives a link to the Alarm Bot example in his comment. Here is a good example of how to create the AutoFac bindings required to use constructor injection.

So using some AutoFac magic and a badly documented aspect of the Bot Framework we can add dependencies as constructor arguments and not have them serialized!

Following the AutoFac guide for WebApi, I first installed Autofac.WebApi2 NuGet package and then updated my Global.asax.cs to look like this:

Now I get all of the usual benefits of doing dependency injection in a more traditional way. I can create mocks and pass them into the dialogue for my tests, the dialogue doesn’t have to worry about where the service comes from and I can more easily control the lifecycle of my dependencies.

Realistically I don’t want to write unit tests against my dialog as there are is too much to mock (IDialogContext does a lot of stuff!) but now I can easily extract my conversational logic to another class and test it in isolation but that’s for another post!

EDIT: this DI approach has since stopped working for me despite being the officially documented strategy. I’ve opened an issue on the Bot Framework’s GitHub. There’s been some discussion and it has since been tagged with “bug” but it doesn’t look like it’s going anywhere fast. Stay tuned for more updates!