0

I try to resolve a handler by this suggested solution with the help of StructureMap.Microsoft.DependencyInjection

I have an Azure Function, QueueTrigger which gets a message and tries to find the right handler for the message. For this function, I use DI and here is the Startup class

[assembly: FunctionsStartup(typeof(Api.Startup))]
namespace Api
{
  public class Startup : FunctionsStartup
  {
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.ConfigureIoc();
    }
  }
}

ConfigureIoC class is like this

 public static class Configuration
{
    public static IServiceProvider ConfigureIoc(this IServiceCollection services)
    {
        services.AddService();
        services.AddCosmosDb();

        IContainer container = new Container();
        container.Configure(configure: config =>
        {
            config.For<IHandler>().Add<xHandler>().Named("handlerName");
            config.Populate(services);
        });

        return container.GetInstance<IServiceProvider>();
    }
}

The function is like this

 public class NameOfFunction
{
    private readonly IxProcessor _xProcessor;

    public NameOfFunction(IxProcessor xProcessor)
    {
        _xProcessor = xProcessor;
    }

    [FunctionName("FunctionName")]
    public async void Run([QueueTrigger("x-queue", Connection = "AzureWebJobsStorage")]string myQueueItem, ILogger log)
    {
        log.LogInformation($"Starting to process scheduled report job: {myQueueItem}");

        try
        {
            await _xProcessor.Process(myQueueItem);
        }
        catch (Exception ex)
        {
            log.LogError($"Exception while processing job queue event: {myQueueItem}. Exception: {ex}");
            throw;
        }
    }
}

The place I need to use those registered for IHandler is used in IxProcessor which is

   public sealed class xProcessor : IxProcessor
{
    private readonly IContainer _container;

    public xProcessor(IContainer container)
    {
        _container = container;
    }

    public async Task Process(string xMessage)
    {
        var jObject = JsonConvert.DeserializeObject<JObject>(xMessage);
        var xName = jObject["Name"].ToString();

        var handler = _container.GetInstance<IHandler>(xName);
        await handler.Handle(xMessage);
    }
}

But it seems the container is null. (IContainer belongs to StructureMap)

    public xProcessor(IContainer container)
    {
        _container = container;
    }

I do not know exactly what do I miss during this configuration. Does anyone have any idea/hint?

ShrnPrmshr
  • 353
  • 2
  • 5
  • 17
  • The linked example is from a previous version of the framework that would no longer work and also not with azure functions. – Nkosi Nov 14 '19 at 13:21
  • This may be a [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Having to inject the container into a service can be seen as a code smell. What are you actually trying to achieve. Maybe an alternative can be found. – Nkosi Nov 14 '19 at 13:22
  • @Nkosi please feel free to give me your suggestion to solve this issue! I have mentioned what is the actual problem I tried to solve by that solution "I have an Azure Function, QueueTrigger which gets a message and tries to find the right handler for the message" – ShrnPrmshr Nov 15 '19 at 10:51

1 Answers1

0

For using DI in Azure function, you may refer to the official tutorial: Use dependency injection in .NET Azure Functions

What you need is the Microsoft.Azure.Functions.Extensions package. And then just add your service in the build-in container:

    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {

            builder.Services.AddSingleton((s) => {
                return new MyService();
            });

            builder.Services.AddSingleton<IService, Service>();
        }
    }

Finally, you can inject services in the constructor.

Jack Jia
  • 5,268
  • 1
  • 12
  • 14