问题
I've read and asked some questions on how to use DI using WebJob and especially Triggered Webjobs.
- SimpleInjector - Azure WebJob with TimerTrigger - Register IDisposable
- Dependency injection using Azure WebJobs SDK?
I still try to figure out how to integrate gracefully DI in triggered webjobs and @Steven asked me a good question :
Isn't there a way to wrap the execution of your service in some scope? For instance, MVC and Web API have an IDependencyScope abstraction for this. This notifies the starting and ending of a request. To be able to do scoping, you either need to have such interception point or you need to be able to wrap the call to JobActivator.
I know that I can start a scope inside my triggered function but I would like to know if there are any point of extensibility in the sdk that allow us to do scoping ?
Thanks.
回答1:
I've opened an request Add IDependencyScope to handle scoping to the Azure Webjob team.
I've create a small library to gather classes around Azure Webjobs and SimpleInjector :
- Nuget download
- GitHub project
For QueueTrigger and ServiceBustrigger, I've come accross these solutions :
ServiceBusTrigger (from this answer: https://stackoverflow.com/a/33759649/4167200):
public sealed 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 ScopedMessageProcessor(_config.MessageOptions, _container); } private class ScopedMessageProcessor : MessageProcessor { private readonly Container _container; public ScopedMessageProcessor(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) { _container.GetCurrentExecutionContextScope()?.Dispose(); return base.CompleteProcessingMessageAsync(message, result, cancellationToken); } } }
You can use your custom MessagingProvider in your JobHostConfiguration like
var serviceBusConfig = new ServiceBusConfiguration { ConnectionString = config.ServiceBusConnectionString }; serviceBusConfig.MessagingProvider = new ScopedMessagingProvider(serviceBusConfig, container); jobHostConfig.UseServiceBus(serviceBusConfig);
QueueTrigger:
public sealed class ScopedQueueProcessorFactory : IQueueProcessorFactory { private readonly Container _container; public ScopedQueueProcessorFactory(Container container) { _container = container; } public QueueProcessor Create(QueueProcessorFactoryContext context) { return new ScopedQueueProcessor(context, _container); } private class ScopedQueueProcessor : QueueProcessor { private readonly Container _container; public ScopedQueueProcessor(QueueProcessorFactoryContext context, Container container) : base(context) { _container = container; } public override Task<bool> BeginProcessingMessageAsync(CloudQueueMessage message, CancellationToken cancellationToken) { _container.BeginExecutionContextScope(); return base.BeginProcessingMessageAsync(message, cancellationToken); } public override Task CompleteProcessingMessageAsync(CloudQueueMessage message, FunctionResult result, CancellationToken cancellationToken) { _container.GetCurrentExecutionContextScope()?.Dispose(); return base.CompleteProcessingMessageAsync(message, result, cancellationToken); } } }
You can use your custom IQueueProcessorFactory in your JobHostConfiguration like this:
var config = new JobHostConfiguration(); config.Queues.QueueProcessorFactory = new ScopedQueueProcessorFactory(container);
来源:https://stackoverflow.com/questions/35186456/azure-triggered-webjobs-scope-for-dependency-injection