C#中的依赖注入:初学者简易指南

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

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

开始课程

C#中的依赖注入:初学者简易指南



依赖注入(DI)是现代C#和.NET开发中的关键设计模式之一。如果你刚刚开始编程之旅,这个术语可能看起来很复杂,但实际上它要简单得多。在本文中,我们将探讨什么是依赖注入,为什么需要它,以及如何在实际中使用它。



用简单的话说,什么是依赖注入?



想象一下你正在组装一台电脑。你可以购买一个现成的主机,里面所有东西都已经焊死且无法更换。或者,你可以用单独的组件来组装它:CPU、显卡、内存。第二种方法要灵活得多——你可以轻松地将显卡换成更强大的,或者添加更多的内存条。



依赖注入的工作原理与此相同。你不是将依赖关系硬“焊死”在类内部(直接在代码中创建对象),而是从外部“注入”它们。这使你的代码变得灵活、可测试且易于维护。



让我们看一个没有DI的糟糕示例:



public class EmailService{    private SmtpClient _client;        public EmailService()    {        // 硬耦合——类自己创建依赖        _client = new SmtpClient("smtp.example.com", 587);    }        public void Send(string to, string message)    {        _client.Send(to, message);    }}


现在,使用DI的相同示例:



public class EmailService{    private readonly ISmtpClient _client;        // 依赖通过构造函数注入    public EmailService(ISmtpClient client)    {        _client = client;    }        public void Send(string to, string message)    {        _client.Send(to, message);    }}


区别很明显:在第二种情况下,我们通过接口ISmtpClient工作,具体的实现从外部传入。



C#中依赖注入的主要方式



在C#中,有三种主要的DI实现方式。让我们逐一了解。



1. 通过构造函数注入



这是最流行且推荐的方式。依赖关系通过构造函数参数传递并保存在私有字段中。



public class OrderService{    private readonly IEmailService _emailService;    private readonly ILogger _logger;        public OrderService(IEmailService emailService, ILogger logger)    {        _emailService = emailService;        _logger = logger;    }        public void ProcessOrder(Order order)    {        _logger.Log("订单处理已开始");        _emailService.Send(order.CustomerEmail, "您的订单已接受");        _logger.Log("订单处理已完成");    }}


2. 通过属性注入



依赖关系通过公共属性设置。当依赖关系是可选的时,这种方法很方便。



public class ReportGenerator{    public ILogger Logger { get; set; }        public void GenerateReport()    {        Logger?.Log("正在生成报告...");        // 生成逻辑    }}


3. 通过方法注入



依赖关系直接传递给需要它的方法。通常很少使用,但在某些场景下可能有用。



public class DataProcessor{    public void ProcessData(string data, IValidator validator)    {        if (validator.Validate(data))        {            // 数据处理        }    }}


实际示例:从糟糕代码到优秀代码



让我们看看DI如何改进实际代码。假设我们有一个用于处理数据库的类。



糟糕的代码(没有DI):



public class UserRepository{    private SqlConnect                

博客

书籍推荐