18_三种服务的生命周期:Singleton、Scoped 和 Transient

三种服务的生命周期:Singleton、Scoped 和 Transient

Singleton

  • Singleton(单例):这种服务只会被创建一次,并且在整个应用程序中重复使用。
  • 这意味着所有使用这种服务的类都会得到同一个服务实例。这种服务适合用于创建成本高昂或需要全局共享的服务,
  • 例如数据库连接或配置信息。您可以使用 AddSingleton 方法注册 Singleton 服务,例如:
services.AddSingleton<IProductService, ProductService>();

这行代码告诉容器,当有类需要 IProductService 时,就提供一个 ProductService 的实例,并且只创建一次,一直保持在内存中。¹

Scoped

  • Scoped(范围内):这种服务每次请求(Request)都会被创建一次,并且在同一个请求中重复使用。这意味着在处理一个请求时,所有使用这种服务的类都会得到同一个服务实例,
  • 但是不同的请求会得到不同的服务实例。这种服务适合用于创建和请求相关的服务,
  • 例如 Entity Framework 的上下文(Context),它可以跟踪和保存请求的数据变化。您可以使用 AddScoped 方法注册 Scoped 服务,例如:
services.AddScoped<IProductService, ProductService>();

这行代码告诉容器,当有类需要 IProductService 时,就提供一个 ProductService 的实例,并且每个请求都创建一个新的实例,请求结束后销毁。¹

Transient

  • Transient(临时):这种服务每次请求(Request)都会被创建,但是不会在请求中重复使用。
  • 这意味着每次使用这种服务的类都会得到一个新的服务实例,即使是在同一个请求中。
  • 这种服务适合用于创建轻量级、无状态的服务,例如日志记录或验证的服务。

您可以使用 AddTransient 方法注册 Transient 服务,例如:

services.AddTransient<IProductService, ProductService>();

这行代码告诉容器,当有类需要 IProductService 时,就提供一个 ProductService 的实例,并且每次都创建一个新的实例,使用完后销毁。¹

比喻

为了帮助您更好地理解这三种服务的生命周期,我可以用一个比喻来说明。假设您去一家餐厅吃饭,餐厅的服务就相当于 ASP.NET Core 的服务,而您的订单就相当于一个请求。那么:

  • Singleton 服务就像是餐厅的老板,他只有一个,而且在餐厅开业期间一直在场。无论您点什么菜,他都会亲自为您服务,并且记住您的喜好。他对所有的客人都是如此,所以他很忙,也很累,但是他很有经验,也很负责。

  • Scoped 服务就像是餐厅的服务员,他们每个人都负责一桌客人。当您进入餐厅时,会有一个服务员为您服务,他会为您点菜、上菜、结账,直到您离开餐厅。如果您再次来到餐厅,可能会遇到同一个服务员,也可能会遇到不同的服务员,但是他们都会为您提供专业的服务。他们对每桌客人都是如此,所以他们也很忙,但是他们很专注,也很友好。

  • Transient 服务就像是餐厅的厨师,他们每次都会为您做新鲜的菜。当您点了一个菜时,会有一个厨师为您做这个菜,并且只做这个菜,做完后就不再管您了。如果您再次点了同一个菜,可能会有同一个厨师为您做,也可能会有不同的厨师为您做,但是他们都会为您做出美味的菜。他们对每个菜都是如此,所以他们很快,也很灵活,但是他们不太关心您的其他需求。

实际例子

Singleton服务 -- 配置信息(Configuration)

  • Singleton 服务:一个常见的使用 Singleton 服务的场景是配置信息(Configuration)。配置信息通常是在应用程序启动时从文件或数据库中读取的,它们在整个应用程序中是不变的,所以没有必要每次都重新读取。您可以使用 AddSingleton 方法将 IConfiguration 接口注册为 Singleton 服务,然后在任何需要配置信息的地方注入它,例如:
services.AddSingleton<IConfiguration>(Configuration);

这样,您就可以在控制器或其他服务中使用 IConfiguration 的实例来访问配置信息,例如:

public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult Index()
{
var title = _configuration["AppSettings:Title"];
ViewBag.Title = title;
return View();
}
}

Scoped 服务 -- Entity Framework Core 的上下文(DbContext)

  • Scoped 服务:一个常见的使用 Scoped 服务的场景是 Entity Framework Core 的上下文(DbContext)。DbContext 是用于操作数据库的类,它可以跟踪和保存每个请求的数据变化。您可以使用 AddDbContext 方法将 DbContext 注册为 Scoped 服务,然后在需要操作数据库的地方注入它,例如:
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

这样,您就可以在控制器或其他服务中使用 AppDbContext 的实例来操作数据库,例如:

public class ProductController : Controller
{
private readonly AppDbContext _context;
public ProductController(AppDbContext context)
{
_context = context;
}
public IActionResult Index()
{
var products = _context.Products.ToList();
return View(products);
}
}

- Transient 服务 -- 日志记录(Logging)

  • Transient 服务:一个常见的使用 Transient 服务的场景是日志记录(Logging)。日志记录是用于记录应用程序的运行情况的服务,它通常是轻量级的,不需要保持状态。您可以使用 AddLogging 方法将 ILoggerFactory 接口注册为 Transient 服务,然后在需要记录日志的地方注入它,例如:
services.AddLogging();

这样,您就可以在控制器或其他服务中使用 ILoggerFactory 的实例来创建日志记录器,例如:

public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<HomeController>();
}
public IActionResult Index()
{
_logger.LogInformation("Index action executed");
return View();
}
}
posted @   甜饼怪2030  阅读(337)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示