作用域是 .NET Core 依赖注入 (DI) 中的一个关键概念。它决定了注入到应用程序中的服务的生命周期和可见性。理解作用域的工作原理可以帮助你更高效地管理资源,避免常见的陷阱,如内存泄漏和不必要的对象创建。本文将探讨什么是作用域、.NET Core 中可用的不同作用域类型,以及如何通过实际示例使用它们。
.NET Core 中的作用域类型
Transient(瞬时): 每次请求都会创建服务的新实例。 Scoped(作用域): 每个请求(或每个作用域)创建一个服务实例。 Singleton(单例): 在整个应用程序的生命周期中共享一个服务实例。
在 .NET Core 中使用作用域
让我们深入了解如何通过示例使用这些作用域。
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>();
}
在控制器中使用该服务:
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{
private readonly ITransientService _transientService1;
private readonly ITransientService _transientService2;
public ExampleController(
ITransientService transientService1,
ITransientService transientService2)
{
_transientService1 = transientService1;
_transientService2 = transientService2;
}
[HttpGet]
public IActionResult Get()
{
return Ok(new
{
Service1 = _transientService1.GetOperationId(),
Service2 = _transientService2.GetOperationId()
});
}
}
每次访问该端点时,你会看到每个服务实例的不同 GUID。
2. Scoped(作用域)
作用域服务在每个请求中只创建一次。这对在单个请求中需要保持状态的服务非常有用。
public interface IScopedService
{
Guid GetOperationId();
}
public class ScopedService : IScopedService
{
private readonly Guid _operationId;
public ScopedService()
{
_operationId = Guid.NewGuid();
}
public Guid GetOperationId() => _operationId;
}
在 Startup.cs
中注册服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IScopedService, ScopedService>();
}
在控制器中使用该服务:
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{
private readonly IScopedService _scopedService1;
private readonly IScopedService _scopedService2;
public ExampleController(IScopedService scopedService1, IScopedService scopedService2)
{
_scopedService1 = scopedService1;
_scopedService2 = scopedService2;
}
[HttpGet]
public IActionResult Get()
{
return Ok(new
{
Service1 = _scopedService1.GetOperationId(),
Service2 = _scopedService2.GetOperationId()
});
}
}
每次访问该端点时,在单个请求中你会看到相同的 GUID,但不同请求之间会有不同的 GUID。
3. Singleton(单例)
单例服务在应用程序的整个生命周期中创建一次并共享。这适用于可共享的无状态服务。
public interface ISingletonService
{
Guid GetOperationId();
}
public class SingletonService : ISingletonService
{
private readonly Guid _operationId;
public SingletonService()
{
_operationId = Guid.NewGuid();
}
public Guid GetOperationId() => _operationId;
}
在 Startup.cs
中注册服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISingletonService, SingletonService>();
}
在控制器中使用该服务:
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{
private readonly ISingletonService _singletonService1;
private readonly ISingletonService _singletonService2;
public ExampleController(ISingletonService singletonService1, ISingletonService singletonService2)
{
_singletonService1 = singletonService1;
_singletonService2 = singletonService2;
}
[HttpGet]
public IActionResult Get()
{
return Ok(new
{
Service1 = _singletonService1.GetOperationId(),
Service2 = _singletonService2.GetOperationId()
});
}
}
每次访问该端点时,你会看到相同的 GUID,在所有请求中都保持一致。
总结
在 .NET Core 中理解并使用合适的服务作用域对资源管理和应用性能至关重要。Transient 服务适用于轻量级无状态操作,Scoped 服务适用于在请求中保持状态的服务,而 Singleton 服务适用于整个应用程序范围内共享的无状态服务。通过慎重选择合适的作用域,你可以优化应用程序的性能和可维护性。
希望这篇文章能帮助你理解 .NET Core 中的作用域概念及其有效的使用方法。如果你有任何疑问,请留言讨论!
译文:c-sharpcorner.com/article/understanding-and-using-scope-in-net-core/
关注公众号↑↑↑:DotNet开发跳槽❀