在单例服务中使用瞬态服务

ask*_*ids 3 c# dependency-injection asp.net-web-api asp.net-core asp.net-core-3.1

我正在使用 ASP.Net Core 3.1 Web API。当我调用控制器操作方法时,我需要在后台执行额外的活动,而不需要在当前操作的处理中添加太多延迟。我正在执行的其他活动是将一些数据准备到缓存中,以便在用户执行下一步之前可用。所以我想简单地触发该活动,而不等待它完成。但同时,我不希望任务在没有完成的情况下被处置,只是因为操作方法完成了它的处理,将响应返回给调用者并且瞬态控制器被处置。

所以我计划使用注入控制器的单例服务来执行任务。但任务本身可能涉及需要使用临时服务。因此,我不是直接将瞬态服务注入到 Singleton Service 中,而是考虑将瞬态服务注入到 Controller 中。然后在操作方法中,我将瞬态服务作为参数传递给单例服务上的异步方法,然后在该方法中调用所需的服务。

public IActionResult GetSomething(string input1)
{
  var resp = await _transientService1.GetSomethingElse(input1);
  // I am not awaiting this task
  var backgroundTask = _singletonService1.DoSomethingAsync(_transientService2, resp.someattr);
  return Ok(resp);
}
Run Code Online (Sandbox Code Playgroud)

现在在单例服务中,我将获取所需的数据并将其写入缓存。

public async Task DoSomethingAsync(ITransientService2 myTransientService2, string someParam)
{
   var temp1 = await myTransientService2.GetSomethingNew(someParam);
   var temp2 = await _SingletonService2.WriteCache(temp1);
}
Run Code Online (Sandbox Code Playgroud)

所以我首先想知道这种方法是否有效。如果它有效,我需要注意哪些陷阱或陷阱。

目前,这都是概念性的。否则我会直接尝试一下:)因此出现了问题。

Ste*_*ngs 6

只要您愿意将依赖项作为参数传递,这就可以工作。

如果您不想将瞬态依赖项作为参数传递,另一种选择是将其注入IServiceProvider到单例服务中,并在需要时实例化瞬态服务。

class MySingleton
{
    private readonly IServiceProvider _serviceProvider;

    public MySingleton(IServiceProvider serviceProvider)
    {
         _serviceProvider = serviceProvider;
    }

    public async Task ExecuteAsync()
    {
        // The scope informs the service provider when you're
        // done with the transient service so it can be disposed
        using (var scope = _serviceProvider.CreateScope())
        {
            var transientService = scope.ServiceProvider.GetRequiredService<MyTransientService>();
            await transientService.DoSomethingAsync();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)