• 深入理解.NET Core中作用域的工作原理
  • 发布于 1周前
  • 60 热度
    0 评论
作用域是 .NET Core 依赖注入 (DI) 中的一个关键概念。它决定了注入到应用程序中的服务的生命周期和可见性。理解作用域的工作原理可以帮助你更高效地管理资源,避免常见的陷阱,如内存泄漏和不必要的对象创建。本文将探讨什么是作用域、.NET Core 中可用的不同作用域类型,以及如何通过实际示例使用它们。

.NET Core 中的作用域类型:
Transient(瞬时): 每次请求都会创建服务的新实例。
Scoped(作用域): 每个请求(或每个作用域)创建一个服务实例。

Singleton(单例): 在整个应用程序的生命周期中共享一个服务实例。


在 .NET Core 中使用作用域,让我们深入了解如何通过示例使用这些作用域。
1. Transient(瞬时)
瞬时服务在每次请求时创建一个新实例,适用于轻量级、无状态的服务。
public interface ITransientService
{
    // 堆代码 duidaima.com
    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 服务适用于整个应用程序范围内共享的无状态服务。通过慎重选择合适的作用域,你可以优化应用程序的性能和可维护性。
用户评论