为什么我应该为我的存储库或服务使用
AddScoped()
?为什么不AddSingleton()
?
我知道它们之间的差异,但不明白为什么我不应该使用单例实例来避免为每个请求创建新对象。
你能解释一下吗(最好用例子:))?
正如您所说,您知道其中的区别,所以我不会深入讨论。
您不想为您的存储库或服务使用 addSingleton 的原因是因为您的存储库和服务通常被视为“业务逻辑”和“持久性逻辑”。在您的业务逻辑中,您可能有一些正在设置的类级别变量。这些属性对于每个请求都不会不同,它们将在请求之间共享。 (将它们视为静态属性)。
示例:
假设您有一个用户服务,它将发出请求的用户的用户名设置为类级别变量。
单例逻辑:
现在想象 Bob 向 api 发出请求。用户名将设置为“Bob”。现在想象一下,与此同时,John 向 api 发出请求。用户名将设置为“John”。但由于用户服务是单例,John 和 Bob 共享同一个实例,这意味着 Bob 的用户名也将设置为“John”。
范围逻辑:
想象一下与上面完全相同的场景,但是这次当 John 发出请求时,它不会覆盖 bob 用户名,因为它们是不同的实例。
以下三种方法定义了服务的生命周期,
添加瞬态 每次请求时都会创建瞬态生命周期服务。此生命周期最适合轻量级、无状态服务。
添加范围 每个请求都会创建一次范围内的生命周期服务。
添加单例 单例生命周期服务是在第一次请求时创建的(或者当您在其中指定实例时运行ConfigureServices时),然后每个后续请求都将使用相同的实例。
假设您有一个 aspnet-core 项目。
如果你想在程序运行时只创建一次对象并且每次都使用同一个对象,你应该使用addingleton。
如果你希望一个对象在程序运行时每次收到请求时都再次new(),你应该使用addscoped()。
如果您希望每个请求和响应都 new() 一个对象,则必须使用 AddTransient。
为什么我应该对我的存储库或服务使用 AddScoped()?为什么不使用 AddSingleton() 呢?我知道它们之间的差异,但不明白为什么我不应该使用单例实例来避免为每个请求创建新对象。你能解释一下吗(最好用例子:))?
我认为你不应该这样做。 谁说你应该? 是什么引发了这个问题?
我创建的服务像
input -> service.do_something() -> output
一样工作,而不在服务本身中存储任何属性(对于常见值来说是无状态的,比如配置传递的东西)。
我认为服务中的存储属性在“步骤”之间传递值正是它们不应该做的事情(辅助类或任何其他辅助实用程序的情况不同)。最终应用程序会增长,您将拥有需要一些初始“工作要做”的服务......这些服务会重复数百万次,而只能完成一次。
如果服务会留下一些内存泄漏(并且将会发生),您会注意到您的应用程序使用越来越多的内存,并从新部署的低内存使用率开始。
“作用域”服务已被处置......但内存泄漏正是在处置服务时未释放的一些内存。因此,对于每个实例化/配置(=“范围”),应用程序的使用内存可能会增加。