AddTransient、AddSingleton、AddScoped 三者都应该在什么场景下使用

结论

  • 上层服务避免使用单例,底层服务如组件等或者需要共享内存快的变量使用单例
  • 一般业务服务不可控,且会由不同的人开发,有的会定义私有变量, 类似以前var a=new class(), 然后在a的生命周期里共享私有变量。 而那些帮助类或者数据库访问类等通用组件应该是单例的也就是以前的static类或者单例模式类。

区别

  • AddTransient 每次service请求都是获得不同的实例
  • AddScoped 对于同一个请求返回同一个实例,不同的请求返回不同的实例(注意主线程里新开线程执行的情况,新线程内会认为不再是同一个请求了)
  • AddSingleton 在整个应用程序生命周期中每次获得的都是同一个实例(项目启动-项目关闭)(重新发布或者iis回收?)。

于我个人而言,我比较习惯用AddScoped,但是在一次多线程的开发过程中,出现了问题——当我在class中初始化了一个AddScoped注入的函数,然后开了一个新的线程引用它时,就会dispose掉,这是因为:AddScoped为每个请求创建一个新实例,开一个新的线程,就不能共享主线程里的了,所以要改成始终是共享的AddSingleton。  

  AddSingleton在全局都是共享的,其生命周期最长。

注意事项

 // 注意事项
            /*
             * 上层服务不能使用单例(特殊情况除外),应该使用AddScoped或者AddTransient
             * 举例说明:A服务引用B服务, B引用C服务(C服务中可能引用DEFG...向下不可控)。上层服务A有可能保证到B是单例也用的,但是保证不了C也能单例下可用。
             * 比如var C=new class(),通过C.xx1(),C.xx2()构造出一个完整的变量返回给上层服务。这种类不能单例注入。
             * 比如 var C=new class(),C.xx1("你好"),C.xx2("你好")等都需要用到"你好",那么"你好"一般会抽取成C的私有变量。这种类不能单例注入。
             * 而A服务是单例的,所以A中用到的B,C对于A来说都是单例的了,成为单例A的静态变量了。那么C无论怎么注入对A来说都等同于单例注入。
             * 因此上层服务按道理是不能单例的
             */