C# Azure Function v3 Dependency Injection - assembly scanning with Scrutor

Viewed 1896

I'm trying to use dependency injection with Azure Functions v3. I've used the Startup approach as recommended by Microsoft in the following article:-

https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection

The event is firing correctly which is great. I'm then calling a dependency resolution helper I use across multiple project types.

I use Scrutor to scan the assemblies so that I don't have to manually add each interface to a class (AddTransient, etc). This works great in an ASP.NET Core Web API project, but does not work at all with an Azure Function. My solution dependencies are not being added at all.

This is the code I have:-

    public static void AddSolutionServices(this IServiceCollection services)
    {
        services.Scan(scan => scan
            .FromCallingAssembly()
            .FromApplicationDependencies()
            .AddClasses(classes => classes.Where(types => types.FullName.StartsWith("MyNamespace.")))
            .UsingRegistrationStrategy(RegistrationStrategy.Append)
            .AsMatchingInterface()
            .WithTransientLifetime()
        );
    }

This is the first time I've tried to write an Azure function so I'm wondering if it's not possible to use assembly scanning with this type of application. Any help would be appreciated!

Thanks

UPDATE 08/09/2020

I still had problems using Scrutor for assembly scanning, something to do with the way dlls are loaded at runtime I believe but I'm not 100% sure on this. I ended up having to manually register services/types as per the standard Microsoft documentation. Scrutor was able to work everywhere else but not for Azure Functions. I'm hoping I was doing something wrong but was unable to find a solution.

1 Answers

Thanks for the advice @HariHaran.

I tried to use Autofac and managed to get it working with my ASP .NET Core 3.0 Web API project. The assembly scanning provided by Autofac wasn't working so I had to resort to scanning the calling assembly for my own dlls. I couldn't add the NuGet package you mentioned in your comment (AzureFunctions.Autofac) because there was a conflict of versions between that and Autofac.Extensions.DependencyInjection.

With the new assembly scanning I managed to make for the above Autofac process, I then had another attempt with the built in .NET Core container and Scrutor. This is the helper method I was able to create - this works with both the Web API project and the Azure Function:-

Startup class for Azure Function

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyNamespace.Gateway.Queue.Function.Startup))]
namespace MyNamespace.Gateway.Queue.Function
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSolutionServices();
        }
    }
}

DI Helper used by Web API and Azure Function

using Scrutor;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class DotNetCoreBootstrapper
    {
        public static void AddSolutionServices(this IServiceCollection services)
        {
            string path = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
            List<Assembly> assemblies = new List<Assembly>();
            foreach (string dll in Directory.GetFiles(path, "MyNamespace*.dll"))
            {
                assemblies.Add(Assembly.LoadFrom(dll));
            }

            services.Scan(scan => scan
                .FromAssemblies(assemblies)
                .AddClasses(classes => classes.Where(types => 
types.FullName.StartsWith("MyNamespace.")))
                .UsingRegistrationStrategy(RegistrationStrategy.Append)
                .AsMatchingInterface()
                .WithTransientLifetime()
            );
        }
    }
}
Related