什么是 C# 中的依赖注入 (DI) 以及为什么需要它?
\n\n依赖注入 (Dependency Injection) 是一种设计模式,它使代码更加灵活、可测试和可维护。类不再自己创建它所依赖的对象,而是从外部“注入”这些对象。这是现代 C# 和 .NET 开发所基于的关键原则之一。
\n\n想象一下,您正在编写一个用于发送电子邮件通知的应用程序。如果您的 NotificationService 类直接创建 SmtpClient 的实例,那么当更换邮件服务器或需要使用其他发送方式(例如通过 API)时,您将不得不重写代码。DI 解决了这个问题。
没有依赖注入的问题
\n\n考虑一个典型的糟糕代码示例,其中依赖项是在类内部创建的:
\n\npublic class EmailService\n{\n private SmtpClient _smtpClient;\n\n public EmailService()\n {\n // 硬绑定到特定实现\n _smtpClient = new SmtpClient("smtp.gmail.com", 587);\n }\n\n public void SendEmail(string to, string subject, string body)\n {\n // 发送逻辑\n }\n}\n\npublic class NotificationService\n{\n private EmailService _emailService;\n\n public NotificationService()\n {\n _emailService = new EmailService(); // 硬耦合\n }\n\n public void NotifyUser(string email)\n {\n _emailService.SendEmail(email, "通知", "你好!");\n }\n}\n\n这种方法的缺点:
\n- \n
- 高耦合性:
NotificationService和EmailService类彼此紧密绑定。 \n - 测试困难: 在单元测试中无法将
EmailService替换为 mock 对象。 \n - 扩展困难: 如果需要添加短信通知,则必须更改
NotificationService内部的逻辑。 \n
在 C# 中实现依赖注入
\n\nDI 通过三种主要方法解决这些问题:构造函数注入、属性注入和方法注入。最常用且推荐的方法是 构造函数注入 (Constructor Injection)。
\n\n步骤 1. 创建接口
\n首先,我们定义一个抽象(接口),它描述了发送消息的契约:
\n\npublic interface IMessageSender\n{\n void Send(string to, string message);\n}\n\n步骤 2. 实现具体服务
\n现在,我们创建该接口的几个实现:
\n\npublic class EmailSender : IMessageSender\n{\n public void Send(string to, string message)\n {\n Console.WriteLine($"发送电子邮件至 {to}: {message}");\n }\n}\n\npublic class SmsSender : IMessageSender\n{\n public void Send(string to, string message)\n {\n Console.WriteLine($"发送短信至 {to}: {message}");\n }\n}\n\n步骤 3. 通过构造函数应用 DI
\n现在,NotificationService 类不再自己创建依赖项,而是通过构造函数获取它们:
public class NotificationService\n{\n private readonly IMessageSender _messageSender;\n\n // 通过构造函数注入依赖项\n public NotificationService(IMessageSender messageSender)\n {\n _messageSender = messageSender;\n }\n\n public void Notify(string userContact, string message)\n {\n _messageSender.Send(userContact, message);\n }\n}\n\n现在我们可以轻松地替换实现:
\n\n// 使用电子邮件\nvar emailSender = new EmailSender();\nvar emailNotifier = new NotificationService(emailSender);\nemailNotifier.Notify("user@example.com", "通过电子邮件发送的问候!");\n\n// 使用短信\nvar sms