在ASP.NET Core中,依赖注入(DI)是一项关键特性,它能促进组件之间的松散耦合,使应用程序更具灵活性且更易于测试。依赖注入最重要的方面之一就是理解服务生命周期是如何工作的。掌握这方面的知识有助于你控制服务的生命周期,并优化应用程序中的资源使用情况。
本篇博客将涵盖以下内容:
到读完本篇博客时,你将对如何在ASP.NET Core.NET 9中使用服务生命周期来编写高效、可扩展的应用程序有扎实的理解。
在ASP.NET Core中,当你在依赖注入(DI)容器中注册一项服务时,需要指定它的生命周期。这定义了一个服务实例的存活时长,以及它如何在不同组件和请求之间共享。
选择正确的服务生命周期可确保高效利用资源、优化性能,并在应用程序中保持恰当的关注点分离。若生命周期使用不当,可能会导致内存泄漏、出现意外行为或效率低下等问题。
每次从依赖注入容器中请求瞬态服务时,都会创建一个新的实例。这意味着每次将其注入到控制器或服务中时,都会创建一个新的实例。
当操作是无状态的,或者每个请求都需要服务的一个新实例时,可使用瞬态服务。例如,对于格式化器、映射器或简单计算等实用工具服务来说,瞬态服务是理想的选择。
public interface ITransientService
{
string GetOperationId();
}
public class TransientService : ITransientService
{
private readonly Guid _operationId;
public TransientService()
{
_operationId = Guid.NewGuid();
}
public string GetOperationId()
{
return $"瞬态服务操作ID:{_operationId}";
}
}
在这个示例中,每次请求该服务时,都会生成一个新的Guid
。每个使用者都会获得一个不同的Guid
,这体现了瞬态服务的无状态特性。
在Program.cs
中:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ITransientService, TransientService>();
}
在控制器中:
public class HomeController : Controller
{
private readonly ITransientService _transientService;
public HomeController(ITransientService transientService)
{
_transientService = transientService;
}
public IActionResult Index()
{
var id = _transientService.GetOperationId();
return Content(id);
}
}
关键点:每次访问该控制器时,都会创建一个TransientService
的新实例,从而提供一个唯一的Guid
值。
作用域服务在每个HTTP请求中创建一次,并在参与该请求的组件之间共享。它在同一个请求内可重复使用,但不会在不同请求之间共享。
作用域服务非常适合数据库上下文类(如Entity Framework中的DbContext
)。通常希望在整个请求中使用同一个上下文实例,以确保数据的一致性,并避免多次建立数据库连接。
public interface IScopedService
{
string GetOperationId();
}
public class ScopedService : IScopedService
{
private readonly Guid _operationId;
public ScopedService()
{
_operationId = Guid.NewGuid();
}
public string GetOperationId()
{
return $"作用域服务操作ID:{_operationId}";
}
}
在这种情况下,每个请求会生成一个Guid
,并在同一个请求内重复使用。
在Program.cs
中:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IScopedService, ScopedService>();
}
在控制器中:
public class HomeController : Controller
{
private readonly IScopedService _scopedService;
public HomeController(IScopedService scopedService)
{
_scopedService = scopedService;
}
public IActionResult Index()
{
var id = _scopedService.GetOperationId();
return Content(id);
}
}
关键点:对于每个HTTP请求,都会使用同一个ScopedService
实例。然而,不同的请求将获得不同的实例。
单例服务在整个应用程序的生命周期内只创建一次。该服务的所有使用者都将共享同一个实例,使其成为生命周期最长的类型。
单例服务非常适合那些需要维护全局状态或执行不经常变更的操作的服务,例如日志记录、缓存或配置管理等。
public interface ISingletonService
{
string GetOperationId();
}
public class SingletonService : ISingletonService
{
private readonly Guid _operationId;
public SingletonService()
{
_operationId = Guid.NewGuid();
}
public string GetOperationId()
{
return $"单例服务操作ID:{_operationId}";
}
}
在这里,同一个Guid
会在所有请求和使用者之间共享,因为它是在应用程序启动时生成一次的。
在Program.cs
中:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISingletonService, SingletonService>();
}
在控制器中:
public class HomeController : Controller
{
private readonly ISingletonService _singletonService;
public HomeController(ISingletonService singletonService)
{
_singletonService = singletonService;
}
public IActionResult Index()
{
var id = _singletonService.GetOperationId();
return Content(id);
}
}
关键点:同一个SingletonService
实例会在所有请求中重复使用,使其在应用程序的整个生命周期内持久存在。
理解服务生命周期对于构建可扩展且高效的ASP.NET Core应用程序至关重要。通过为服务选择正确的生命周期,你可以确保资源的最优使用以及代码的可维护性。请记住: