ZetCode

ASP.NET AddScoped

最后修改于 2025 年 4 月 3 日

在本文中,我们将探讨 ASP.NET 8 中的 AddScoped 方法。此方法对于依赖注入和管理服务生命周期至关重要。

ASP.NET 是一个跨平台、高性能的框架,用于构建现代 Web 应用程序。AddScoped 方法有助于有效管理对象生命周期。

基本定义

AddScoped 是 ASP.NET Core 依赖注入系统中的一个方法。它使用范围生命周期注册一个服务。范围服务在每个客户端请求中创建一次。

使用 AddScoped 时,在单个 HTTP 请求中会共享同一个实例。这对于在请求期间维护状态但不需要在请求之间持久化的服务非常理想。

范围服务在请求结束时被释放。它们通常用于数据库上下文、存储库和其他特定于请求的操作。

ASP.NET AddScoped 示例

以下示例演示了如何将 AddScoped 与存储库模式结合使用。

Program.cs
var builder = WebApplication.CreateBuilder(args);

// Register services with different lifetimes
builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.Run();

这使用范围存储库服务设置了依赖注入。AddScoped 方法注册了接口-实现对。

Models/Product.cs
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    
    public Product(int id, string name, decimal price)
    {
        Id = id;
        Name = name;
        Price = price;
    }
}

这个简单的 Product 模型代表了我们的数据结构。它将由我们的存储库和控制器使用。

Repositories/IProductRepository.cs
public interface IProductRepository
{
    IEnumerable<Product> GetAll();
    Product GetById(int id);
    void Add(Product product);
}

该接口定义了我们产品存储库的契约。为了演示目的,它包含了基本的 CRUD 操作。

Repositories/ProductRepository.cs
public class ProductRepository : IProductRepository
{
    private readonly List<Product> _products;
    private readonly ILogger<ProductRepository> _logger;

    public ProductRepository(ILogger<ProductRepository> logger)
    {
        _logger = logger;
        _products = new List<Product>
        {
            new(1, "Laptop", 999.99m),
            new(2, "Mouse", 19.99m),
            new(3, "Keyboard", 49.99m)
        };
        
        _logger.LogInformation("ProductRepository instance created");
    }

    public IEnumerable<Product> GetAll() => _products;

    public Product GetById(int id) => 
        _products.FirstOrDefault(p => p.Id == id);

    public void Add(Product product)
    {
        product.Id = _products.Max(p => p.Id) + 1;
        _products.Add(product);
    }
}

存储库实现管理我们的产品数据。请注意,它包含了用于日志记录的构造函数注入,展示了 DI 中的 DI。

Controllers/ProductsController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductRepository _repository;
    private readonly ILogger<ProductsController> _logger;

    public ProductsController(
        IProductRepository repository,
        ILogger<ProductsController> logger)
    {
        _repository = repository;
        _logger = logger;
    }

    [HttpGet]
    public IActionResult GetAll()
    {
        _logger.LogInformation("Getting all products");
        return Ok(_repository.GetAll());
    }

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        var product = _repository.GetById(id);
        if (product == null)
        {
            _logger.LogWarning("Product {Id} not found", id);
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public IActionResult Add([FromBody] Product product)
    {
        _repository.Add(product);
        _logger.LogInformation("Added product {Id}", product.Id);
        return CreatedAtAction(nameof(GetById), 
            new { id = product.Id }, product);
    }
}

控制器使用构造函数注入来获取范围存储库。每个请求都会获得自己的存储库实例,确保了适当的隔离。

日志记录演示了每个请求都会创建一个新的存储库。尝试发出多个请求以查看日志消息的实际效果。

此示例展示了 AddScoped 如何提供请求级别的服务实例。存储库在整个请求期间维护其状态,但不会在请求之间泄露。

来源

Microsoft ASP.NET 依赖注入文档

在本文中,我们探讨了 ASP.NET 8 中的 AddScoped 方法。这项强大的功能有助于在 Web 应用程序中有效管理服务生命周期。

作者

我叫 Jan Bodnar,是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 ASP.NET 教程