Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Dependency Injection in Azure Functions

Azure Functions V2 supports ASP.NET Core like Dependency Injection. It is specially good if we write functions that are wrappers for shared libraries and components we are also using in web and other applications of our solution. This blog post shows how to use dependency injection in Azure Functions.

To get started with code check out Azure Functions with DI Github repository by @MikaBerglund. It’s simple and minimal Visual Studio solution without any overhead.

Preparing the code

Let’s start with simple classes I previously used in blog post ASP.NET Core: Inject all instances of interface. There’s interface for alerts service and we use here service implementation that sends alert to e-mail. Service uses customer class to get customer e-mail.

public class Customer
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Mobile { get; set; }
}

public interface IAlertService
{
    void SendAlert(Customer c, string title, string body);
}

public class EmailAlertService : IAlertService
{
    public void SendAlert(Customer c, string title, string body)
    {
        if (string.IsNullOrEmpty(c.Email))
        {
            return;
        }

        Debug.WriteLine($"Sending e-mail to {c.Email} for {c.Name}");
    }
}

Azure Functions startup class

There’s startup class supported by Azure Functions V2. It’s similar to one we know from ASP.NET Core but there are differences. To make dependency injection work we must add reference Microsoft.Azure.Functions.Extensions to our Azure Functions project.

After namespaces section in Startup class we have to define FunctionsStartup attribute for assembly.

[assembly: FunctionsStartup(typeof(AzureFunctionsDI.Startup))]

Our functions startup class extends FunctionsStartup class.

public abstract class FunctionsStartup : IWebJobsStartup
{
    protected FunctionsStartup();

    public abstract void Configure(IFunctionsHostBuilder builder);
    public void Configure(IWebJobsBuilder builder);
}

We have to define at least Configure() method that is called with functions host builder.

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddScopedIAlertService, EmailAlertService>();
    }
}

We can add also other service registrations in this method. It seems like functions are on the half-way to Startup class we know from ASP.NET Core.

Injecting instances to Azure Functions

With Azure Functions V2 we can use dependency injection similar to ASP.NET Core. Minimal default HTTP-triggered function is shown here.

public static class Function1
{
    [FunctionName("Function1")]
    public static async TaskIActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        return await Task.FromResult(new OkObjectResult("OK"));
    }
}

To make it work with dependency injection we have to move from static scope to instance scope and use constructor injection like shown here.

public class Function1
{
    private readonly IAlertService _alertService;

    public Function1(IAlertService alertService)
    {
        _alertService = alertService;
    }

    [FunctionName("Function1")]
    public async TaskIActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        var customer = new Customer { Name = "John", Email = "[email protected]" };
        var title = "Emergy alert";
        var body = "The roof is on fire!";

        _alertService.SendAlert(customer, title, body);

        return await Task.FromResult(new OkObjectResult("OK"));
    }
}

Running the functions project and setting break point to line in constructor where IAlertService is assigned allows us see if instance is injected to functions class.

No errors, function is running and we have instance of IAlertService injected to our function.

Injecting all instances of interface

Similar to ASP.NET Core we can also inject all instances of interface to function. I added new implementation of IAlertService to project.

public class SmsAlertService : IAlertService
{
    public void SendAlert(Customer c, string title, string body)
    {
        if (string.IsNullOrEmpty(c.Mobile))
        {
            return;
        }

        Debug.WriteLine($"Sending SMS to {c.Mobile} for {c.Name}");
    }
}

Then I registered it to dependency injection in functions Startup class.

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddScopedIAlertService, EmailAlertService>();
        builder.Services.AddScopedIAlertService, SmsAlertService>();
    }
}

Here is how my function looks with injection of all IAlertService instances.

public class Function1
{
    private readonly IEnumerableIAlertService> _alertServices;

    public Function1(IEnumerableIAlertService> alertServices)
    {
        _alertServices = alertServices;
    }

    [FunctionName("Function1")]
    public async TaskIActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        var customer = new Customer { Name = "John", Email = "[email protected]" };
        var title = "Emergy alert";
        var body = "The roof is on fire!";

        foreach (var alertService in _alertServices)
        {
            alertService.SendAlert(customer, title, body);
        }

        return await Task.FromResult(new OkObjectResult("OK"));
    }
}

Running the function with breakpoint same way as before shows that both registered instances of IAlertService class are injected to function.

Dependency injection with Azure Functions V2 works like dependency injection in ASP.NET Core.

Wrapping up

With Azure Functions V2 we can use same dependency injection mechanism as in ASP.NET Core. There are differences like no support for direct injection through function arguments (ASP.NET Core supports controller action injection) but the basics are all the same.  Support for dependency injection makes it easier to re-use same components and services we are using in web applications through dependency injection.

The post Dependency Injection in Azure Functions appeared first on Gunnar Peipman - Programming Blog.



This post first appeared on Gunnar Peipman - Programming, please read the originial post: here

Share the post

Dependency Injection in Azure Functions

×

Subscribe to Gunnar Peipman - Programming

Get updates delivered right to your inbox!

Thank you for your subscription

×