簡體   English   中英

C#依賴注入無法使用范圍嗎?

[英]C# Dependency Injection Cannot Consume Scoped?

我沒有使用依賴注入的豐富經驗,但是我正在嘗試在我的一個項目中使用它。 當我嘗試向我的構造函數中添加第二個參數時,出現錯誤“無法從單例中使用作用域服務'CarbonService'...”。不確定為什么會收到此錯誤或丟失了什么。 謝謝你的幫助

在此處輸入圖片說明

我希望我的計時器類可以訪問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));
}

ValidUntilTimerService.cs:

// 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; 
  }
  ...
}

CarbonService.cs:

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)
  {
    ...
  }
}

IHostedService被注冊為單例。 您將ICarbonService注入ValidUntilTimerService ,這意味着您將范圍服務注入了單例服務。

如果我們考慮這兩種服務的壽命:

  • 每個請求一次創建范圍服務。 這意味着,在實例化作用域服務時,該服務將保持活動狀態直到請求結束。

  • 當實例化Singleton服務時,它將保持活動狀態,直到應用程序關閉。

我們意識到,從單例服務中使用范圍服務並沒有多大意義。 在這種情況下將發生以下情況:

實例化單例服務(在您的情況下為ValidUntilTimerService )時,其作用域依賴項(在您的情況下為ICarbonService )也被實例化並注入到單例服務中。 請求完成后,單例服務保持活動狀態,但作用域服務被處置。 現在,您的單例服務最終以“ _carbonService ”依賴關系(在您的情況下為_carbonService字段)。

以上情況是不可能的。 這只是一個“假設”場景。 關鍵是, 您不能使用根據請求創建的服務,而無需請求即可創建的服務 (例如,在應用啟動時)。

現在,這說明了問題的原因,但讓我們看看您可以采取什么措施解決問題。

可能的解決方案

您可以使用IServiceScopeFactoryValidUntilTimerService內部創建自己的范圍:

public class ValidUntilTimerService : IHostedService, IDisposable
{
  private readonly ILogger _logger;
  private Timer _timer;
  private IServiceScopeFactory _serviceScopeFactory;

  public ValidUntilTimerService(ILogger<ValidUntilTimerService> logger, IServiceScopeFactory serviceScopeFactory)
  {
    _logger = logger;
    _serviceScopeFactory = serviceScopeFactory; 
  }

  // ...
  using (var scope = _serviceScopeFactory.CreateScope())
  {
     ICarbonService carbonService = scope.ServiceProvider.GetService(typeof(ICarbonService));
    // ...
  }
  // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM