在 .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 | 在整个应用程序生命周期中,只创建一个实例 | 对象的生命周期与应用程序的生命周期一致 | 全局共享的服务,如配置管理、日志记录 |
通过合理选择依赖注入的生命周期,我们可以实现对象的灵活管理和高效使用,从而提高应用程序的性能和可维护性。