细聊.Net Core中IServiceScope的工作方式( 九 )

其实核心逻辑和同步释放是一致的 , 只是IAsyncDisposable接口中的DisposeAsync()方法返回的异步相关的ValueTask所以需要进行一些等待相关的操作 。不过本质都是循环释放_disposables里的数据,而这些数据正是当前作用域里里实现了IDisposable或IAsyncDisposable接口的实例 。

使用CreateScope()GetService()方法的时候,都会判断当前作用域是否释放,而这个标识正是在Dispose()DisposeAsync()置为true的 。我们上面文章中的那个异常的引发点也正是这里 , 也正是因为作用域被释放了表示为置为true了,所以GetService才会直接抛出异常 。
群友问题解答关于ServiceProviderEngineScope重要的相关实现,咱们上面已经大致的讲解过了 。其实探索它的原动力就是因为群友遇到的一些关于这方面的疑问,如果了解了它的实现的话便能轻松的解除心中的疑问 , 还原一下当时有疑问的代码
IServiceCollection services = new ServiceCollection();services.AddScoped<Person>(provider => new() { Id = 1, Name = "yi念之间", Sex = "Man" });IServiceProvider serviceProvider = services.BuildServiceProvider();Person person = null;using (IServiceScope serviceScope = serviceProvider.CreateScope()){    person = serviceScope.ServiceProvider.GetService<Person>();    Console.WriteLine(person.Name);}if (person == null){    Console.WriteLine("Person被回收了");}【细聊.Net Core中IServiceScope的工作方式】代码大致描述的就是当时的这么一个场景,这里毫无疑问哈,完全判断不出来Person是否已经被回收 。通过上面的源码咱们就可以知道 , 无论是掉用ServiceProviderEngineScope的是Dispose()DisposeAsync()方法(using上面咱们说过了就是语法糖),其实都是调用了当前作用域内实现了IDisposableIAsyncDisposable接口的实例里的Dispose()DisposeAsync()方法 。
  • 即使当前实例实现了IDisposableIAsyncDisposable接口,且调用了实例内的Dispose()DisposeAsync()方法,也不意味着当前对象已经被释放了,因为我们用Dispose方法里多半是这个对象里引用的非托管代码的释放工作,并不意味这当前对象被释放了 。
  • IServiceScope实现类ServiceProviderEngineScope里ResolvedServices属性享元的实例,也就是生命周期为ServiceLifetime.Scoped的实例 。这些实例何时被回收是取决于两点 , 一是当前实例的访问是否超出当前作用域,二是当前对象是否有被引用 。上面的示例中IServiceScope实例虽然已经超出作用了(因为在using括号之外了),但是Person外出的栈里还引用着ResolvedServices字典里Person对象的实例,所以GC即垃圾回收机制并不会回收这个实例,因为它还在被引用 。那就意味着它不能被释放,也就不存在Person实例被回收这么一说了 。
所以,上面的问题说起来就是IServiceScope主要解决的是对象取的问题 , 也就是我用我的字典属性保留了需要保留的对象实例,可以释放被声明可以释放的操作(比如非托管资源的释放) 。但是作用域本身的回收和内部管理的对象的回收是交给GC来负责的 。
细想一下就会明白了 , 托管对象的回收本身就是垃圾回收处理的,就和你自己写单例模式或者直接new一个对象实例的时候,你也没考虑对象的回收问题,因为垃圾回收机制已经帮你处理了 。
总结在.Net Core体系中IOC一直是核心模块 , 且关于Scope的作用域的问题,一直会有人产生疑问,想更深刻的了解一下还是得多拿一些时间研究一下 。有些知识不是靠一时半会的学就能牢牢地掌握,需要日常不断的积累和不断的解决问题,才能掌握的更多 。因为设计到的源码比较多,而且不熟悉的话可能不是很好理解,所以还需要平时的积累,积累的越多能解决的问题越多,才能避免入坑 。好了大致总结一下