在 .NET Core 中,依赖注入(Dependency Injection,DI)是一种实现控制反转(Inversion of Control,IoC)的技术,它通过将依赖对象注入到需要它们的对象中,来实现对象之间的解耦。依赖注入的生命周期决定了对象在应用程序中的创建和管理方式。常见的生命周期有三种:Transient(瞬态)、Scoped(作用域) 和 Singleton(单例)。
1. Transient(瞬态)
定义:
每次请求时都会创建一个新的实例。
特点:
- 每次注入时都会创建一个新的对象。
- 对象的生命周期仅限于当前请求。
- 适用于轻量级、无状态的服务。
使用场景:
- 适用于每次请求都需要独立实例的场景,例如工具类、无状态服务等。
示例:
public interface ITransientService { Guid GetOperationId(); } public class TransientService : ITransientService { private readonly Guid _operationId; public TransientService() { _operationId = Guid.NewGuid(); } public Guid GetOperationId() => _operationId; }
在 Startup.cs 中注册:
public void ConfigureServices(IServiceCollection services) { services.AddTransient<ITransientService, TransientService>(); }
在控制器中使用:
public class HomeController : Controller { private readonly ITransientService _transientService1; private readonly ITransientService _transientService2; public HomeController(ITransientService transientService1, ITransientService transientService2) { _transientService1 = transientService1; _transientService2 = transientService2; } public IActionResult Index() { _transientService1.DoWork(); _transientService2.DoWork(); // 验证是否为不同实例 Console.WriteLine(_transientService1 == _transientService2); // 输出:False return Ok(); } }
输出:
Transient Service: Doing work... Transient Service: Doing work... False
2. Scoped(作用域)
定义:
在同一个作用域内,对象是单例的;但在不同的作用域中,会创建新的实例。
特点:
- 对象的生命周期与请求的作用域一致。
- 适用于需要在请求范围内共享状态的服务。
使用场景:
- 适用于需要在请求范围内共享状态的场景,例如数据库上下文、工作单元模式等。
示例:
public interface IScopedService { void DoWork(); } public class ScopedService : IScopedService { public void DoWork() { Console.WriteLine("Scoped Service: Doing work..."); } }
在 Startup.cs 中注册
public void ConfigureServices(IServiceCollection services) { services.AddScoped<IScopedService, ScopedService>(); }
在控制器中使用:
public class HomeController : Controller { private readonly IScopedService _scopedService1; private readonly IScopedService _scopedService2; public HomeController(IScopedService scopedService1, IScopedService scopedService2) { _scopedService1 = scopedService1; _scopedService2 = scopedService2; } public IActionResult Index() { _scopedService1.DoWork(); _scopedService2.DoWork(); // 验证是否为相同实例 Console.WriteLine(_scopedService1 == _scopedService2); // 输出:True return Ok(); } }
输出:
Scoped Service: Doing work... Scoped Service: Doing work... True
3. Singleton(单例)
定义:
在整个应用程序生命周期中,只创建一个实例。
特点:
- 对象的生命周期与应用程序的生命周期一致。
- 适用于全局共享的服务,如配置管理、日志记录等。
使用场景:
- 适用于需要全局共享的场景,例如配置管理、缓存、日志记录等。
示例:
public interface ISingletonService { void DoWork(); } public class SingletonService : ISingletonService { public void DoWork() { Console.WriteLine("Singleton Service: Doing work..."); } }
在 Startup.cs 中注册:
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<ISingletonService, SingletonService>(); }
在控制器中使用:
public class HomeController : Controller { private readonly ISingletonService _singletonService1; private readonly ISingletonService _singletonService2; public HomeController(ISingletonService singletonService1, ISingletonService singletonService2) { _singletonService1 = singletonService1; _singletonService2 = singletonService2; } public IActionResult Index() { _singletonService1.DoWork(); _singletonService2.DoWork(); // 验证是否为相同实例 Console.WriteLine(_singletonService1 == _singletonService2); // 输出:True return Ok(); } }
输出:
Singleton Service: Doing work... Singleton Service: Doing work... True
总结
| 生命周期 | 定义 | 特点 | 使用场景 |
|---|---|---|---|
| Transient | 每次请求时创建新的实例 | 每次注入时都会创建一个新的对象 | 轻量级、无状态的服务,如工具类、无状态服务 |
| Scoped | 在同一个作用域内,对象是单例的 | 对象的生命周期与请求的作用域一致 | 需要在请求范围内共享状态的服务,如数据库上下文 |
| Singleton | 在整个应用程序生命周期中,只创建一个实例 | 对象的生命周期与应用程序的生命周期一致 | 全局共享的服务,如配置管理、日志记录 |
通过合理选择依赖注入的生命周期,我们可以实现对象的灵活管理和高效使用,从而提高应用程序的性能和可维护性。