細聊.Net Core中IServiceScope的工作方式

2022-10-17 12:01:30

前言

    自從.Net Core引入IOC相關的體系之後,關於它的討論就從來沒有停止過,因為它是.Net Core體系的底層框架,你只要使用了.Net Core的時候就必然會用到它。當然關於使用它的過程中產生的問題也從來沒停止過。我對待問題的態度向來都是,如果你踩到了坑,說明你還沒有足夠了解它,所以我們對它認知的突破,很多時候是遇到了問題並解決了問題。今天的話題呢,也是一個群友在研究.Net Core作用域的過程中產生的疑問,博主呢對這個問題也很有興趣,就藉此機會探究了一下,把自己研究結果分享給大家。

簡單演示

在日常的開發中使用CreateScope()CreateAsyncScope()的場景可能沒有那麼多,但是在ASP.NET Core底層的話這是核心設計,在上篇文章<解決ASP.NET Core在Task中使用IServiceProvider的問題>中提到過,ASP.NET Core會為每次請求建立一個Scope,也就是咱們這次提到的作用域。使用的方法有很簡單,本質就是IServiceProvider的一個擴充套件方法。咱們今天主要說的就是ServiceLifetime.Scoped這個比較特殊的生命週期,在Scope內是如何工作的,原始點的寫法其實就是

IServiceCollection services = new ServiceCollection();
services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之間", Sex = "Man" });

IServiceProvider serviceProvider = services.BuildServiceProvider();
using (IServiceScope serviceScope = serviceProvider.CreateScope())
{
    var personOne = serviceScope.ServiceProvider.GetService<Person>();
    Console.WriteLine(person.Name);
}

如果在ASP.NET Core框架裡那玩法就多了,只要有IServiceProvide的地方都可以使用CreateScope()CreateAsyncScope()方法,簡單演示一下,但是如果感覺自己把握不住的話還是提前自己試驗一下

[HttpGet]
public async Task<object> JudgeScope([FromServices]IServiceProvider scopeProvider)
{
    using IServiceScope scope = HttpContext.RequestServices.CreateScope();
    Person person = scope.ServiceProvider.GetService<Person>();

    await using (AsyncServiceScope scope2 = scopeProvider.CreateAsyncScope())
    {
        Person person2 = scope2.ServiceProvider.GetService<Person>();
    }
    return person;
}

原始碼探究

通過上面的範例,我們可以看到其實關於IServiceScope的操作部分就是三個核心。

  • 通過CreateScope()CreateAsyncScope()方法建立服務作用域。
  • 使用GetService相關的方法建立需要的物件範例。
  • 用完了作用域之後通過使用Dispose()或者DisposeAsync()方法(using的方式同理)釋放作用域。

先說AsyncServiceScope

為了怕大家心裡有疑慮,因為使用CreateScope()方法建立出來的是IServiceScope範例,使用CreateAsyncScope方法建立的是AsyncServiceScope範例。咱們這裡先來說一下AsyncServiceScopeIServiceScope的關係,看了之後大家就不用惦記它了,先來看一下CreateAsyncScope()方法的定義[點選檢視原始碼