练习 - 探索服务生存期
在上一练习中,你使用单一实例服务生存期注册了服务。 在代码评审中,团队主管要求调查单一实例、作用域和暂时性服务生存期之间的差异。
测试单一实例服务生存期
如果之前的练习中已经运行了应用,那么它应当仍在运行。 如果没有如期运行,请按照之前的方式运行应用。
刷新浏览器窗口并留意欢迎消息中显示的时间。
等待几秒钟,然后再次刷新浏览器窗口。 欢迎消息没有变化。 时间戳和 GUID 保持不变。
欢迎消息中显示的时间和 GUID 没有变化,因为
WelcomeService
服务注册为单一实例服务。 在应用启动时创建一次服务,并在应用的生存期内重复使用。 每个客户端的每个请求都使用相同的服务实例。 不会创建其他服务实例。通过在 Visual Studio Code 中按 Shift+F5 来停止应用。
测试作用域服务生存期
要了解作用域服务生存期,需要更改注册 WelcomeService
服务的方式。
在 Program.cs 文件中,更改
WelcomeService
服务的注册以使用作用域服务生存期:builder.Services.AddScoped<IWelcomeService, WelcomeService>();
此代码将
WelcomeService
类注册到具有作用域生存期的服务容器。请按照之前的方式运行应用。
请留意欢迎消息中显示的时间和 GUID。 刷新浏览器窗口并注意每次时间都会变化,GUID 也是不同的。
欢迎消息中显示的数据会变化,因为
WelcomeService
服务现已注册为作用域服务。 每个客户端请求都会单独创建一次服务,请求完成后,该服务就会被释放。 每个客户端的每个请求都使用新的服务实例。通过在 Visual Studio Code 中按 Shift+F5 来停止应用。
让我们来探讨一下,在同一个请求中尝试使用同一
WelcomeService
服务的两个实例时,作用域服务生存期的行为。 将app.MapGet()
行更改为以下代码:app.MapGet("/", async (IWelcomeService welcomeService1, IWelcomeService welcomeService2) => { string message1 = $"Message1: {welcomeService1.GetWelcomeMessage()}"; string message2 = $"Message2: {welcomeService2.GetWelcomeMessage()}"; return $"{message1}\n{message2}"; });
在上述代码中:
-
app.MapGet()
委托现在有两个类型均为IWelcomeService
的参数。 委托会生成两条欢迎消息,每个服务实例各一条。 - 委托在单个响应中返回这两条消息。
-
请按照之前的方式运行应用。 请注意,即使两条欢迎消息是在不同时间生成的,并且它们是作为单独的参数传递给委托的,但消息内容是相同的。
此行为是因为
WelcomeService
服务注册为作用域服务。 该服务是针对每个客户端请求单独创建的,在同一个请求中,所有需要它的组件都会获得同一个实例。welcomeService1
和welcomeService2
都引用WelcomeService
服务的同一实例。多次刷新页面。 请注意,欢迎消息中的时间戳和 GUID 每次都会变化,但两条消息始终相同。
通过在 Visual Studio Code 中按 Shift+F5 来停止应用。
测试暂时性服务生存期
现在,让我们检查暂时性服务生存期。
更改
WelcomeService
服务的注册以使用暂时性服务生存期:builder.Services.AddTransient<IWelcomeService, WelcomeService>();
此代码将
WelcomeService
类注册到具有暂时性生存期的服务容器。请按照之前的方式运行应用。 这两条消息中的时间保持不变,因为
WelcomeService
服务的两个实例是同时创建的。 但是,每个消息中的 GUID 不同,因为每个服务实例都是唯一的。此行为代表暂时性服务生存期。 每次将服务注入组件时,都会创建新的服务实例。 由于它注入到委托中两次,因此会创建两个服务实例。
多次刷新页面。 每次刷新页面时,两个消息中的时间戳始终相同,但每个消息中的 GUID 不同。
通过在 Visual Studio Code 中按 Shift+F5 来停止应用。