我已阅读并询问有关如何使用WebJob以及特别是Triggered Webjobs使用DI的一些问题。
我仍然试图弄清楚如何在触发的webjobs中优雅地整合DI,并且@Steven问我一个很好的问题:
是否有办法将服务的执行包裹在某个范围内?例如,MVC和Web API具有 IDependencyScope 抽象。这会通知请求的开始和结束。为了能够进行作用域,你需要有这样的拦截点,或者你需要能够将调用包装到JobActivator。
我知道我可以在触发函数中启动一个范围,但我想知道sdk中是否有任何可扩展性点允许我们进行范围设定?
感谢。
答案 0 :(得分:4)
我已向Azure Webjob小组打开了请求Add IDependencyScope to handle scoping。
我创建了一个小型库来收集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);
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);
}
}
}
您可以在JobHostConfiguration中使用自定义IQueueProcessorFactory,如下所示:
var config = new JobHostConfiguration();
config.Queues.QueueProcessorFactory = new ScopedQueueProcessorFactory(container);