具有范围依赖性的 .Net Core 2.0 Webjob

.Net Core 2.0 Webjob with Scoped Dependencies

我正在使用 IJobActivator 设置 .Net Core 2.0 来构建网络作业。 IServiceScopeFactory.CreateScope 如果 Functions 是作用域的,则似乎在 IJobActivator 中不起作用,如果它是单例,则在 Functions 中也不起作用。

public static void Main(string[] args)
{
    IServiceCollection serviceCollection = new ServiceCollection();

    serviceCollection.AddScoped<Functions>(); //Or serviceCollection.AddSingleton<Functions>();
    serviceCollection.AddScoped<TelemetryScopeProvider>();
    //... Other scoped dependecies e.g. EF context and repositories.

    var serviceProvider = serviceCollection.BuildServiceProvider(true);

    var jobHostConfiguration = new JobHostConfiguration();
    jobHostConfiguration.Queues.MaxPollingInterval = TimeSpan.FromSeconds(10);
    jobHostConfiguration.Queues.BatchSize = 1;
    jobHostConfiguration.JobActivator = new ProcessorActivator(serviceProvider);
    jobHostConfiguration.UseServiceBus();

    jobHostConfiguration.NameResolver = new QueueNameResolver()
    {
        ResultQueueName = ...
    };

    var config = new JobHostConfiguration();
    var host = new JobHost(jobHostConfiguration);
    host.RunAndBlock();
}

public class ProcessorActivator : IJobActivator
{
    private readonly IServiceProvider _service;
    private IServiceScopeFactory _scopeFactory;

    public ProcessorActivator(IServiceProvider service, IServiceScopeFactory scopeFactory)
    {
        _service = service;
        _scopeFactory = scopeFactory;
    }

    public T CreateInstance<T>()
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var service = _service.GetService(typeof(T));
            return (T)service;
        }
    }

public class Functions
{
    private IServiceScopeFactory _scopeFactory;
    private IServiceProvider _serviceProvider;

    public Functions(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
        _serviceProvider = serviceProvider;
    }

    public async Task ProcessValidationResult([ServiceBusTrigger("%Response%")
 ] string r)
    {
        var start = DateTime.UtcNow;
        using (var scope = _scopeFactory.CreateScope())
        {
            try
            {
                //Deserialize the result.
                var result = JsonConvert.DeserializeObject...;

                var scopeProvider = _serviceProvider.GetService<TelemetryScopeProvider>(); //FAIL HERE

            //Some other Logic which we dont get to
            }
            catch (Exception e)
            {
                Console.Out.WriteLine($"Error processing: {e.Message}");
            }
        }
    }

如果 Functions 是作用域的:异常将在激活器中抛出:无法解析来自根提供者的作用域服务 'ValidationResultProcessorWebJob.Functions'。

如果 Functions 是单例:System.InvalidOperationException: 无法从根提供程序解析作用域服务 'ValidationResultProcessorWebJob.TelemetryScopeProvider'。

是否未应用_scopeFactory.CreateScope()?为什么不呢?

谢谢,

韦恩

我错误地认为 IServiceScopeFactory 提供了比它更多的魔力。据我目前了解,应该使用 IServiceScopeFactory.CreateScope 创建子作用域。 IServiceScope 包含一个 ServiceProvider,然后可用于实例化新的依赖关系图。

我将逻辑从函数移至新处理器 class 并将其配置为 Scoped。

serviceCollection.AddScoped<Functions>();
serviceCollection.AddScoped<ResponseProcesor>();
//... Other scoped dependecies e.g. EF context and repositories. 

我将 IServiceScopeFactory 注入 WebJobs class(函数)并从中实例化一个新的对象图。

public class Functions
{
    private IServiceScopeFactory _scopeFactory;

    public Functions(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public async Task ProcessValidationResult([ServiceBusTrigger("%Response%")] string r)
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var processor = scope.ServiceProvider.GetService<ResponseProcesor>();
            await processor.Process(r);
        }
    }
}