ZetCode

ASP.NET IServiceCollection

最后修改于 2025 年 4 月 3 日

在本文中,我们将探讨 ASP.NET 8 中的 IServiceCollection。此接口是 ASP.NET 应用程序中依赖注入的基础。依赖注入是现代 .NET 开发中的一项关键设计模式。

IServiceCollection 提供了将应用程序服务注册到不同生命周期的方法。然后,这些服务可以注入到控制器、中间件和其他组件中。这促进了松耦合和可测试性。

基本定义

IServiceCollection 是一个接口,代表服务描述符的集合。它是 Microsoft.Extensions.DependencyInjection 命名空间的一部分。该接口提供了将服务注册到 DI 容器的方法。

服务可以根据三种不同的生命周期进行注册:瞬时(transient)、作用域(scoped)和单例(singleton)。瞬时服务在每次请求时创建。作用域服务在每个客户端请求时创建一次。

单例服务只创建一次,并在应用程序的整个生命周期中重用。IServiceCollection 通常在应用程序启动期间在 Program.cs 文件中配置。

ASP.NET IServiceCollection 示例

以下示例演示了如何使用 IServiceCollection 在 ASP.NET 8 应用程序中配置服务。

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

// Configure services
builder.Services.AddControllers();
builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddSingleton<ILoggerService, FileLoggerService>();

var app = builder.Build();

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

此代码配置了三个具有不同生命周期的服务。AddScoped 方法注册了一个存储库,该存储库将为每个 HTTP 请求创建一次。AddTransient 在每次请求时创建一个新的电子邮件服务实例。

AddSingleton 注册了一个日志服务,该服务将在应用程序的整个生命周期中共享。AddControllers 方法添加了对 MVC 控制器的支持。

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> GetAllProducts();
    Product GetProductById(int id);
    void AddProduct(Product product);
}

IProductRepository 接口定义了我们的产品数据访问的契约。它包括检索和添加产品的方法。

Repositories/ProductRepository.cs
public class ProductRepository : IProductRepository
{
    private readonly List<Product> _products = new()
    {
        new Product(1, "Laptop", 999.99m),
        new Product(2, "Mouse", 19.99m),
        new Product(3, "Keyboard", 49.99m)
    };

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

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

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

ProductRepository 实现 IProductRepository 接口。它为了演示目的使用了内存列表。在实际应用程序中,这将连接到数据库。

Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductRepository _productRepository;
    private readonly ILoggerService _logger;

    public ProductsController(
        IProductRepository productRepository,
        ILoggerService logger)
    {
        _productRepository = productRepository;
        _logger = logger;
    }

    [HttpGet]
    public IActionResult GetAllProducts()
    {
        _logger.Log("Fetching all products");
        return Ok(_productRepository.GetAllProducts());
    }

    [HttpGet("{id}")]
    public IActionResult GetProductById(int id)
    {
        var product = _productRepository.GetProductById(id);
        if (product == null)
        {
            _logger.Log($"Product with id {id} not found");
            return NotFound();
        }
        return Ok(product);
    }
}

ProductsController 展示了依赖注入的实际应用。IProductRepository 和 ILoggerService 通过构造函数注入。控制器使用这些服务来处理 HTTP 请求。

GetAllProducts 方法从存储库返回所有产品。GetProductById 方法通过 ID 检索特定产品。这两种方法都利用了注入的服务。

来源

Microsoft 依赖注入文档

在本文中,我们探讨了 ASP.NET 8 中的 IServiceCollection。这项强大的功能实现了现代应用程序中清晰的依赖管理。正确使用依赖注入可以带来更易于维护和测试的代码。

作者

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

列出所有 ASP.NET 教程