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?
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.
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.
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.
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); } }
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With