我已阅读并询问了一些有关如何通过 WebJob 特别是触发式 Webjobs 使用 DI 的问题。
- SimpleInjector - Azure WebJob with TimerTrigger - Register IDisposable
- Dependency injection using Azure WebJobs SDK?
我仍在尝试弄清楚如何在触发的 webjobs 中优雅地集成 DI,@Steven 问了我一个很好的问题:
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.
我知道我可以在触发函数内启 Action 用域,但我想知道 sdk 中是否有任何可扩展点允许我们进行作用域界定?
谢谢。
最佳答案
我已打开一个请求 Add IDependencyScope to handle scoping致 Azure Webjob 团队。
我创建了一个小型库来收集有关 Azure Webjobs 和 SimpleInjector 的类:
对于 QueueTrigger 和 ServiceBustrigger,我遇到过以下解决方案:
ServiceBusTrigger(来自此答案: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); } } }
您可以在 JobHostConfiguration 中使用自定义 MessagingProvider,例如
var serviceBusConfig = new ServiceBusConfiguration { ConnectionString = config.ServiceBusConnectionString }; serviceBusConfig.MessagingProvider = new ScopedMessagingProvider(serviceBusConfig, container); jobHostConfig.UseServiceBus(serviceBusConfig);
队列触发器:
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); } } }
您可以在 JobHostConfiguration 中使用自定义 IQueueProcessorFactory,如下所示:
var config = new JobHostConfiguration(); config.Queues.QueueProcessorFactory = new ScopedQueueProcessorFactory(container);
关于Azure 触发的 Webjobs 依赖项注入(inject)范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35186456/