在 ASP.NET Core 中创建单例服务的正确方法 - 它是否必须使用 static 关键字?

Proper way to create a singleton service in ASP.NET Core - does it have to use the static keyword, or not?

这让我很困惑。没有什么能阻止我们创建带有实例字段的 class 和 实例方法,而不是使用静态字段和静态方法创建 class。两者都可以注册为单例。

是否有解决此问题的首选方法,为什么?

编辑: 我不是在问如何使用单例模式创建 class。我问的是单例依赖注入 class 与注入相同的 class 但静态定义 members/fields/methods/properties.

您需要了解DI的不同lifetimes和您的需求,才能选择合适的寿命。

  • Transient 每次请求服务时都会创建服务(因此如果在 1 次请求中,服务被使用 2 次,它将被创建 2 次)。
  • Scoped 服务是根据网络请求创建的(因此,如果在 1 个请求中,服务被使用了 2 次,它将只创建一次)。
  • Singleton 是一个将持续整个应用程序生命周期的实例(所有请求将共享这个实例)。

如有疑问,请将其设为瞬态。

编辑

我想值得一提的是,如果您将服务创建为 Transient,并且它们具有您不断更改的静态属性,那么这将影响所有其他创建的实例,因为 static 影响类型本身,而不是比一个实例。

I'm asking about [...] injecting the same class but with static defined members/fields/methods/properties

这是可能的,但没用。如果一个控制器需要这样一个单例对象,那么你仍然没有实例方法来调用这个对象。您的控制器必须在 class.

上调用静态方法

[...] creating a class with instance fields and instance methods

这是更好的方法,因为它允许您模拟对象以进行单元测试。

如果你想要具体的例子,我已经编写了 class with instance methods to store data about users, which is registered as a singleton object, and used in controller.

希望它能让你更清楚。

静态 class 字段可以由同一 class 的其他实例修改。通过将 class 注册为具有静态字段的单例,您将依赖这样一个事实,即永远不会在应用程序的任何其他部分创建相同 class 的任何其他实例。

我意识到您将专注于从 DI 获取实例 - 但是,如果应用程序中的任何地方有一点 class 的另一个实例是直接实例化而不是通过 DI - 静态 属性 将暴露于其状态(值)的潜在变化。

使用单例实例 properties/fields 将确保您只使用由您从 DI 获得的实例控制的 properties/fields。