Dependency Injection with Azure Functions and FunctionsStartup

Picture: Microsoft

Dependency Injection with Azure Functions and FunctionsStartup

Azure Functions provides a very lean way to execute code serverless. So lean, in fact, that there is no dependency injection by default.

With the help of NuGet and the Azure Function Extensions, however, Dependency Injection can be easily retrofitted, as the pattern itself is naturally supported.

Required NuGet Packages

First of all you need those NuGet Packages

Code

All the magic is done by FunctionsStartup.

With the help of FunctionsStartup we can configure our services in a startup class, e.g. from ASP.NET Core.

In principle, it is even possible to outsource the entire Statup content and share it with other .NET Core environments. The signatures and the behavior is identical to all other startup configurations. It is fully compatible.

[assembly: FunctionsStartup(typeof(MyCompany.MyApp.Startup))]
namespace MyCompany.MyApp
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // Http Client
            builder.Services.AddHttpClient();

            // Analaytic Options
            builder.Services.Configure<AnalyticsOptions>(options =>
                {
                    options.Url = Environment.GetEnvironmentVariable("ANALYTICS_SERVICE_API");
                });
            builder.Services.AddScoped<IAnalyticsService, NoiseAnalyticsService>();

            // Notification
            builder.Services.AddScoped<INotificationProvider, NotificationProvider>();

            // Engine
            builder.Services.AddMediatR(typeof(DeviceProcessingEngine));
        }
    }
}

In the Azure Function Trigger, the respective instance of a service or another class can now simply be specified via the constructor as usual, so that it can be used in the class.

public class IoTHubMessageProcessor
{
    private readonly IMediator _mediator;

    public IoTHubMessageProcessor(IMediator mediator)
    {
        _mediator = mediator;
    }

    [FunctionName("iot-hub-message")]
    public async Task Run(
        [EventHubTrigger("device-sensor-events", 
            Connection = "AZURE_EVENT_HUB_DTSENSOR_INGEST_CONNECTIONSTRING")] EventData[] eventData,
        ILogger log)
    {
        if (eventData is null)
        {
            log.LogWarning($"Received sensor event but no messages were passed.");
            return;
        }