How to implement dependency injection in azure functions

Azure Functions are the stars in the Azure serverless stack: Compute resources on-demand. We can build functions to react to different types of events, such as HTTP requests, file processing or to run scheduled tasks. But the beauty here is that if more compute resources are needed, Azure will scale-out automatically those resources to meet the demand. When the high-load is finished and the resources are no longer in need, then Azure will scale back, even to zero if that’s the case.

As we build Azure Functions we should keep our design as clean as possible. Functions are defined to respond to a variety of triggers and execute business logic afterward. You may develop lightweight functions but you are able to put in complex design as well. This post is about how to plug-in Dependency Injection into Azure Functions to make our code more organized and decoupled.

Let’s create an Azure Function in VS2019. Using the Service Bus trigger, we will be sitting in front of this structure:

Taking a quick look we won’t see any Program.cs or Startup.cs  but taking a look insight Function1.cs we will see that the well-known ILogger interface is been passed. Who is doing this magic?

That’s the Azure Function SDK that recognizes the annotation [FunctionName("Function1")] for the Run() method and the [ServiceBusTrigger()] for the first parameter and knows what to do on the build. Then, it will be the Azure Function Runtime that will start our function and pass down the ILogger for us. 

What if we want to leverage dependency injection in order to design a more complex app? Can we have something like Startup.cs and have our services registered there? 

Indeed, but first, we need to install a NuGet package: Microsoft.Azure.Functions.Extensions, then we can create our Startup class and make it inherits from the FunctionsStartup class present in the namespace Microsoft.Azure.Functions.Extensions.DependencyInjection.

Second, we need to register our class as the Startup, instead of the default used by the runtime. We do that by using the [assembly] annotation as follows:

At this point, we have our IFunctionsHostBuilder object and with it, we can register our services as needed. For this demo, I have created the IEventAggregator interface and the EventAggregator class. We should register our logging capacity as well.

Of course, we can use any of the service lifecycles available such as TransientSingleton or Scoped

The next step is to inject our IEventAggregator service into our function. For that, we need a bit of refactoring making our function class not-static and passing our service via the constructor.  

And that’s it, we now have the Startup class and our IFunctionsHostBuilder available to register services as we need. Remember, to make this code sample work, you need an Azure Service Bus connection, subscription and topic!

I hope this helps you and makes you save an hour or two on research! 😉 Leave me a comment if it did.