gpt4 book ai didi

c# - 如何在后台任务中使用具有依赖性的作用域服务

转载 作者:太空狗 更新时间:2023-10-30 01:28:56 27 4
gpt4 key购买 nike

这是我的场景。我想使用后台任务向订阅用户发送时事通讯。这是由 MailService 完成的,它具有 UnitOfWork 作为依赖项。

我尝试了 learn.microsoft.com 中的解决方案所以在我的例子中,我使用了 IMailService 的方法而不是 ILogger,但是我得到了一个错误:

System.InvalidOperationException: 'Cannot consume scoped service >'Fit4You.Core.Data.IUnitOfWork' from singleton >'Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor'.'

我不想让我的 UnitOfWork 或 DbContext 具有单例生命周期。是否有可能以某种方式使用 MailService 的依赖项,它是作用域 UnitOfWork?

我知道 IServiceScopeFactory 但可能不知道如何正确使用它。

我正在使用 .NET Core 2.2 并在接口(interface) IHostedService 中构建

ScopedMailService:

public class ScopedMailService : IScopedMailService
{
private readonly IMailService mailService;

public ScopedMailService(IMailService mailService)
{
this.mailService = mailService;
}

public void DoWork()
{
mailService.SendNewsletterToSubscribedUsers();
}
}

ConsumeScopedMailService:

public class ConsumeScopedMailService : IHostedService
{
private Timer timer;
private readonly IMailService mailService;
public IServiceProvider Services { get; }

public ConsumeScopedMailService(IServiceProvider services, IMailService mailService)
{
Services = services;
this.mailService = mailService;
}

public Task StartAsync(CancellationToken cancellationToken)
{
var startTimeSpan = GetStartTimeSpan();
var periodTimeSpan = TimeSpan.FromSeconds(30);

timer = new Timer(DoWork, null, startTimeSpan, periodTimeSpan);

return Task.CompletedTask;
}

private void DoWork(object state)
{
using (var scope = Services.CreateScope())
{
var scopedMailService = scope.ServiceProvider.GetRequiredService<IScopedMailService>();
scopedMailService.DoWork();
}
}

public Task StopAsync(CancellationToken cancellationToken)
{
timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}

public void Dispose()
{
timer?.Dispose();
}

private TimeSpan GetStartTimeSpan()
{
var currentTime = DateTime.Now.Ticks;
var executeTime = DateTime.Today.AddHours(8)
.AddMinutes(0)
.Ticks;

long ticks = executeTime - currentTime;

if (ticks < 0)
{
ticks = ticks + TimeSpan.TicksPerDay;
}

var startTimeSpan = new TimeSpan(ticks);

return startTimeSpan;
}
}

启动.cs:

public void ConfigureServices(IServiceCollection services)
{
...

services.AddDbContext<Fit4YouDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));

services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddTransient<IMailService, MailService>();

services.AddHostedService<ConsumeScopedMailService>();
services.AddScoped<IScopedMailService, ScopedMailService>();

...
}

邮件服务:

    public class MailService : IMailService
{
private readonly IUnitOfWork unitOfWork;
public MailService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}

public void SendNewsletterToSubscribedUsers()
{
// Some Code
}
}

最佳答案

单例 ConsumeScopedMailService 通过其构造函数依赖于 IMailService :

public ConsumeScopedMailService(IServiceProvider services, IMailService mailService)

IMailService 可能是 transient 的,但实现它的类取决于作用域 服务,IUnitOfWork。间接地,ConsumeScopedMailService 最终取决于作用域服务。

要修复此 IMailService mailService 应该被删除。无论如何,它没有在发布的代码中使用。

关于c# - 如何在后台任务中使用具有依赖性的作用域服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55413655/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com