Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection using Azure WebJobs SDK?

The problem is that the Azure WebJobs SDK supports only public static methods as job entry-points which means there is no way of implementing constructor/property injection.

I am unable to find anything about this topic in official WebJobs SDK documentation/resources. The only solution that I came across is based on service locator (anti) pattern described on this post here.

Is there a good way to use "proper" dependency injection for projects based on Azure WebJobs SDK?

like image 512
Milos Mrdovic Avatar asked May 19 '15 14:05

Milos Mrdovic


People also ask

What is azure WebJobs SDK?

The Azure WebJobs SDK is a framework that simplifies the task of writing background processing code that runs in Azure WebJobs. It includes a declarative binding and trigger system that works with Azure Storage Blobs, Queues and Tables as well as Service Bus.

What is azure WebJobs used for?

WebJobs is a feature of Azure App Service that enables you to run a program or script in the same instance as a web app, API app, or mobile app. There is no additional cost to use WebJobs. You can use the Azure WebJobs SDK with WebJobs to simplify many programming tasks.

What is the difference between Azure Functions and WebJobs?

Summary. Azure Functions offers more developer productivity than Azure App Service WebJobs does. It also offers more options for programming languages, development environments, Azure service integration, and pricing. For most scenarios, it's the best choice.


2 Answers

Azure WebJobs SDK now supports instance methods. Combining this with a custom IJobActivator allows you to use DI.

First, create the custom IJobActivator that can resolve a job type using your favourite DI container:

public class MyActivator : IJobActivator {     private readonly IUnityContainer _container;      public MyActivator(IUnityContainer container)     {         _container = container;     }      public T CreateInstance<T>()     {         return _container.Resolve<T>();     } } 

You need to register this class using a custom JobHostConfiguration:

var config = new JobHostConfiguration {     JobActivator = new MyActivator(myContainer) }; var host = new JobHost(config); 

Then, you can use a simple class with instance methods for your jobs (here I'm using Unity's constructor injection feature):

public class MyFunctions {     private readonly ISomeDependency _dependency;      public MyFunctions(ISomeDependency dependency)     {         _dependency = dependency;     }      public Task DoStuffAsync([QueueTrigger("queue")] string message)     {         Console.WriteLine("Injected dependency: {0}", _dependency);          return Task.FromResult(true);     } } 
like image 199
Sander Molenkamp Avatar answered Sep 17 '22 14:09

Sander Molenkamp


This is how I handled scoping using the new SDK. Using the IJobactivator as described by Alexander Molenkamp.

public class ScopedMessagingProvider : MessagingProvider {     private readonly ServiceBusConfiguration _config;     private readonly Container _container;      public ScopedMessagingProvider(ServiceBusConfiguration config, Container container)         : base(config)     {         _config = config;         _container = container;     }      public override MessageProcessor CreateMessageProcessor(string entityPath)     {         return new CustomMessageProcessor(_config.MessageOptions, _container);     }      private class CustomMessageProcessor : MessageProcessor     {         private readonly Container _container;          public CustomMessageProcessor(OnMessageOptions messageOptions, Container container)             : base(messageOptions)         {             _container = container;         }          public override Task<bool> BeginProcessingMessageAsync(BrokeredMessage message, CancellationToken cancellationToken)         {             _container.BeginExecutionContextScope();             return base.BeginProcessingMessageAsync(message, cancellationToken);          }          public override Task CompleteProcessingMessageAsync(BrokeredMessage message, FunctionResult result, CancellationToken cancellationToken)         {             var scope = _container.GetCurrentExecutionContextScope();             if (scope != null)             {                 scope.Dispose();             }              return base.CompleteProcessingMessageAsync(message, result, cancellationToken);         }     } } 

You can the use your custom MessagingProvider in your JobHostConfiguration like

var serviceBusConfig = new ServiceBusConfiguration {      ConnectionString = config.ServiceBusConnectionString }; serviceBusConfig.MessagingProvider = new ScopedMessagingProvider(serviceBusConfig, container); jobHostConfig.UseServiceBus(serviceBusConfig); 
like image 24
Niklas Arbin Avatar answered Sep 18 '22 14:09

Niklas Arbin