C# 中的依赖注入:完整指南及示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C#中的依赖注入:是什么以及为什么需要它



Dependency Injection (DI) 是一种关键的设计模式,它允许在C#中创建松耦合且易于测试的应用程序。类不再自己创建其依赖项(例如,用于数据库操作或日志记录的对象),而是从外部传递(注入)这些依赖项。这实现了控制反转 (IoC) 原则——控制权被移交给外部容器。



在.NET生态系统中,从ASP.NET Core开始,DI已成为事实上的标准。内置的依赖注入容器(通过Microsoft.Extensions.DependencyInjection)可以轻松注册和解析依赖项。在本文中,我们将探讨DI的理论、实际示例以及C#中的最佳实践。



依赖注入的基本原则



DI基于三种基本的依赖注入方式。我们来逐一分析。



1. 构造函数注入

这是最常见且首选的方式。依赖项通过类的构造函数参数传递。



public interface ILogger{    void Log(string message);}

public class ConsoleLogger : ILogger{ public void Log(string message) => Console.WriteLine(message);}

public class OrderService{ private readonly ILogger _logger;

// 通过构造函数注入依赖项 public OrderService(ILogger logger) { _logger = logger; }

public void ProcessOrder(int orderId) { _logger.Log($"处理订单 {orderId}"); // 业务逻辑 }}


2. 属性注入

依赖项通过公共属性设置。这种方式不太推荐,因为它使依赖项变为可选,并可能导致运行时错误。



public class OrderService{    public ILogger Logger { get; set; }

public void ProcessOrder(int orderId) { if (Logger == null) throw new InvalidOperationException("Logger未设置"); Logger.Log($"处理订单 {orderId}"); }}


3. 方法注入

依赖项作为方法参数传递。很少使用,通常用于临时依赖项。



public class OrderService{    public void ProcessOrder(int orderId, ILogger logger)    {        logger.Log($"处理订单 {orderId}");    }}


在.NET容器中注册依赖项



在现代.NET(ASP.NET Core、控制台应用、Worker Services)中,使用内置的DI容器。注册发生在ConfigureServices方法中,或者在创建ServiceCollection时进行。



已注册的服务有三种生命周期:



  • Transient — 每次请求时都会创建一个新实例。适用于轻量级、短生命周期的服务。
  • Scoped — 每个HTTP请求(或作用域)一个实例。用于Entity Framework的DbContext。
  • Singleton — 整个应用程序一个实例。适用于缓存、配置、日志记录器。


// ASP.NET Core示例public class Startup{    public void ConfigureServices(IServiceCollection services)    {        // 使用接口注册        services.AddTransient<ILogger, ConsoleLogger>();        services.AddScoped<IOrderRepository, OrderRepository>();        services.AddSingleton<IConfiguration, ConfigurationManager>();

// 不使用接口注册(具体类) services.AddTransient<OrderService>(); }}

// 在控制器中使用public class OrderController : ControllerBase{ private readonly OrderService _orderService;

public OrderController(OrderServi

博客

书籍推荐