做外贸soho网站的公司,一般营销方式三大步骤,seo 网站地图优化,自己做的网站能放到网上么前言上一小节简单阐述了依赖注入及Asp.NetCore中自带依赖注入组件的常规用法#xff0c;其中提到容器管控了自己创建对象的生命周期#xff0c;包含了三种生命周期#xff1a;Singleton、Scoped、Transient#xff0c; 对于Singleton、Transient相对于Scoped来说比较好理解… 前言 上一小节简单阐述了依赖注入及Asp.NetCore中自带依赖注入组件的常规用法其中提到容器管控了自己创建对象的生命周期包含了三种生命周期Singleton、Scoped、Transient 对于Singleton、Transient相对于Scoped来说比较好理解其实这里面有一个作用域的概念也可以理解为根容器和子容器的范围上一小节中有一个例子中说到当注入的生命周期为Scoped的时在同一个请求内注入的对象都是同一个这里Asp.NetCore将每个请求作为了一个作用域在此作用域内生命周期为Scoped的对象就是同一个下面简单说说作用域和对象释放的常规知识点正文 作用域这里可以理解为服务范围由IServiceScope承载如其源代码所示每一个服务范围内都一个根容器如下所示//// 摘要:// /// The System.IDisposable.Dispose method ends the scope lifetime. Once Dispose// /// is called, any scoped services that have been resolved from /// Microsoft.Extensions.DependencyInjection.IServiceScope.ServiceProvider// will be /// disposed. ///public interface IServiceScope : Object, IDisposable{// IServiceProvider 即代表容器//// 摘要:// /// The System.IServiceProvider used to resolve dependencies from the scope.// ///IServiceProvider ServiceProvider{get;}}每一个服务范围内可以通过自身IServiceProvider创建对应的子作用域而任何一个子作用域的IServiceProvider都有对根容器的引用如下图结构 每一个IServiceProvider中都会将其创建的对象存入列表中针对于继承与IDisposable接口的类型对象会单独存放在一个列表中当作用域IServiceScope对象的Dispose方法被调用时最终对应IServicePorvider对应的对象列表也会清空针对于继承与IDisposable类型的对象会调用其Dispose方法最后导致对应作用域下容器创建的对象成为垃圾对象被GC给回收 在Asp.NetCore中框架默认将其分有根作用域(与引用程序同生命周期)和请求作用域(每一个请求一个作用域)通常也会称其为根容器和请求容器名称分别为ApplicationServices和RequestServices在程序中获取方式如下 通过IApplicationBuilder对象可以获取ApplicationServices 通过HttpContext.RequestServices获取RequestServices 作用域简单举例在请求作用域下再创建子作用域分别查看对应不同生命周期对象是否一致新建一个WebApi项目针对三个生命周期添加了对应文件结构如下 对应红框内的文件内容如下 细心的小伙伴可能会看到每个实现类里面都继承了IDisposable接口这主要是后面显示释放用的这里先不管编辑好以上内容之后就将其进行注册如下 接下来就是使用了这里通过这Action中使用在当前的请求作用域下创建子作用域对比每一个生命周期对象如代码所示[HttpGet]
public string Get([FromServices]ITestSingleton testSingleton, [FromServices]ITestSingleton testSingleton1,[FromServices]ITestScoped testScoped, [FromServices]ITestScoped testScoped1,[FromServices]ITestTransient testTransient, [FromServices]ITestTransient testTransient1)
{//获取请求作用域(请求容器)var requestServices HttpContext.RequestServices;//在请求作用域下创建子作用域using(IServiceScope scope requestServices.CreateScope()){//在子作用域中通过其容器获取注入的不同生命周期对象ITestSingleton testSingleton11 scope.ServiceProvider.GetServiceITestSingleton();ITestScoped testScoped11 scope.ServiceProvider.GetServiceITestScoped();ITestTransient testTransient11 scope.ServiceProvider.GetServiceITestTransient();ITestSingleton testSingleton12 scope.ServiceProvider.GetServiceITestSingleton();ITestScoped testScoped12 scope.ServiceProvider.GetServiceITestScoped();ITestTransient testTransient12 scope.ServiceProvider.GetServiceITestTransient();Console.WriteLine(Singleton);Console.WriteLine($请求作用域的ITestSingleton对象:{testSingleton.GetHashCode()});Console.WriteLine($请求作用域的ITestSingleton1对象:{testSingleton1.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestSingleton11对象:{testSingleton11.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestSingleton12对象:{testSingleton12.GetHashCode()});Console.WriteLine(Scoped);Console.WriteLine($请求作用域的ITestScoped对象:{testScoped.GetHashCode()});Console.WriteLine($请求作用域的ITestScoped1对象:{testScoped1.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestScoped11对象:{testScoped11.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestScoped12对象:{testScoped12.GetHashCode()});Console.WriteLine(Transient);Console.WriteLine($请求作用域的ITestTransient对象:{testTransient.GetHashCode()});Console.WriteLine($请求作用域的ITestTransient1对象:{testTransient1.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestTransient11对象:{testTransient11.GetHashCode()});Console.WriteLine($请求作用域下子作用域的ITestTransient12对象:{testTransient12.GetHashCode()});}return TestServiceScope;}运行进行请求看打印结果 对于Singleton来说始终不变因为其是跟随根容器生命周期引用程序退出才释放 对于Scoped来说只要在自己的作用域内就是单例的 对于Transient来说始终创建 以上一直在说释放下面利用继承IDisposable接口释放时会调用对应Dispoable方法的原理简单演示各个生命周期的释放时机在Controller中增加几个Action方法如下 这里使用IHostApplicationLifetime中的StopApplication模拟关闭程序释放单例下的对象运行看效果 使用坑不要从根容器中获取Transient生命周期的对象因为通过根容器创建的对象不会回收除非等到应用程序退出这样会导致内存泄露如下演示 新增Action方法运行发送请求看结果总结 作用域及对象释放就简单说这么多容器只管理自己创建出来的对象生命周期下一节说说使用第三方组件扩展依赖注入功能