C# 依赖项注入不能使用作用域?

C# 依赖项注入不能使用作用域?,c#,dependency-injection,C#,Dependency Injection,我没有太多使用依赖注入的经验,但我正试图在我的一个项目中使用它。当我尝试向我的构造函数添加第二个参数时,我得到一个错误“无法从singleton使用作用域服务“CarbonService…”不确定为什么会出现此错误或缺少什么。谢谢你的帮助 我希望我的timer类能够访问CarbonService对象 Startup.cs: public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCo

我没有太多使用依赖注入的经验,但我正试图在我的一个项目中使用它。当我尝试向我的构造函数添加第二个参数时,我得到一个错误“无法从singleton使用作用域服务“CarbonService…”不确定为什么会出现此错误或缺少什么。谢谢你的帮助

我希望我的timer类能够访问CarbonService对象

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  services.AddDbContext<CarbonDBContext>(o => o.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
  services.AddHostedService<ValidUntilTimerService>();
  services.AddScoped<ICarbonService, CarbonService>();  // I HAVE TRIED USING SINGLETON BUT SAME ERROR 

  services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
}

IHostedService
s被注册为单例。您正在将
ICarbonService
注入到
validuntilimerservice
中,这意味着您正在将作用域服务注入到单例服务中

如果我们考虑这两种服务的寿命:

  • 每个请求创建一次作用域服务。这意味着,当实例化作用域服务时,它将一直保持活动状态,直到请求结束

  • 当单例服务被实例化时,它将保持活动状态,直到应用程序关闭

我们意识到从单例服务中使用作用域服务没有多大意义。在这种情况下会发生以下情况:

当singleton服务(
ValidUnitImerService
在您的示例中)被实例化时,其作用域依赖项(
ICarbonService
在您的示例中)也被实例化并注入singleton服务。当请求完成时,单例服务保持活动状态,但作用域服务被释放。现在,您的单例服务以一个“死”依赖项结束(
\u carbonService
字段)

上述情况是不可能的。这只是一个“如果”的场景。关键是,您不能使用根据请求创建的服务,而该服务可以在没有请求的情况下创建(例如,在应用程序启动时)

现在,这就解释了问题的原因,但让我们看看你能做些什么来解决它

可能的解决方案

您可以使用在
ValidUnitImerService
中创建自己的作用域:

public类ValidUntilTimerService:IHostedService,IDisposable
{
专用只读ILogger\u记录器;
私人定时器;
私营IServiceScope工厂(服务范围工厂);;
公共ValidUntilTimerService(ILogger记录器、IServiceScopeFactory服务范围工厂)
{
_记录器=记录器;
_serviceScopeFactory=serviceScopeFactory;
}
// ...
使用(var scope=\u serviceScopeFactory.CreateScope())
{
ICarbonService=scope.ServiceProvider.GetService(typeof(ICarbonService));
// ...
}
// ...
}

您认为该错误的含义可能重复?感谢您的解释。这是有道理的。我提出了你的建议,事情成功了。问题,为什么不更改“services.AddSingleton();”呢?仅供参考,它不会。我试过了
// ADDING THE SECOND PARAMETER TO THIS CONSTRUCTOR CAUSES THE ERROR.
public class ValidUntilTimerService : IHostedService, IDisposable
{
  private readonly ILogger _logger;
  private Timer _timer;
  private ICarbonService _carbonService;

  public ValidUntilTimerService(ILogger<ValidUntilTimerService> logger, ICarbonService carbonService)
  {
    _logger = logger;
    _carbonService = carbonService; 
  }
  ...
}
public interface ICarbonService
{
  WattTime ReadCarbon();
  void SaveCarbon(int carbonIndex);
}

public class CarbonService : ICarbonService
{
  private IConfiguration _configuration;
  private readonly CarbonDBContext _dbcontext;

  public CarbonService(IConfiguration configuration, CarbonDBContext dbContext)
  {
    _configuration = configuration;
    _dbcontext = dbContext;
  }

  public WattTime ReadCarbon()
  {
    var wt = new WattTime();
    ...
    return wt;
  }

  public void SaveCarbon(int carbonIndex)
  {
    ...
  }
}