在现代C#开发中,依赖注入(Dependency Injection, DI)已成为构建松耦合、可测试和可维护应用程序的核心技术。虽然.NET提供了内置的DI容器(如Microsoft.Extensions.DependencyInjection),但理解其底层原理——尤其是手动解析依赖的过程——对于开发者掌握控制反转(Inversion of Control, IoC)思想至关重要。
依赖注入是一种设计模式,它允许我们将一个类所依赖的对象从外部“注入”进来,而不是在类内部直接创建。这样做的好处是:
虽然使用现成的DI容器很方便,但在以下场景中,理解并实现手动解析依赖非常有价值:
下面我们从零开始,用C#编写一个简单的DI容器,用于手动解析依赖。
public interface IEmailService{ void SendEmail(string to, string message);}public class SmtpEmailService : IEmailService{ public void SendEmail(string to, string message) { Console.WriteLine($"发送邮件到 {to}: {message}"); }}public interface ILogger{ void Log(string message);}public class ConsoleLogger : ILogger{ public void Log(string message) { Console.WriteLine($"[日志] {message}"); }} 我们需要一个字典来保存服务类型与其具体实现之间的映射关系。
public class SimpleContainer{ private readonly Dictionary _registrations = new(); public void Register() where TImplementation : TService { _registrations[typeof(TService)] = typeof(TImplementation); }} 关键在于递归地解析构造函数参数所需的依赖。
public object Resolve(Type serviceType){ if (!_registrations.TryGetValue(serviceType, out Type implementationType)) { throw new InvalidOperationException($"未注册服务: {serviceType.FullName}"); } // 获取实现类型的构造函数 var constructor = implementationType.GetConstructors().FirstOrDefault(); if (constructor == null) { return Activator.CreateInstance(implementationType); } // 解析构造函数参数 var parameters = constructor.GetParameters(); var args = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { args[i] = Resolve(parameters[i].ParameterType); } return Activator.CreateInstance(implementationType, args);}// 泛型重载public T Resolve(){ return (T)Resolve(typeof(T));} // 定义一个使用依赖的服务public class NotificationService{ private readonly IEmailService _emailService; private readonly ILogger _logger; public NotificationService(IEmailService emailService, ILogger logger) { _emailService = emailService; _logger = logger; } public void Notify(string user, string message) { _emailService.SendEmail(user, message); _logger.Log($"已通知用户: {user}"); }}// 使用容器var container = new SimpleContainer();container.Register();container.Register();container.Register();var notificationService = container.Resolve();notificationService.Notify("alice@example.com", "您的订单已发货!"); 通过以上步骤,我们实现了一个支持构造函数注入的简易DI容器。虽然它不具备生命周期管理、作用域支持等高级功能,但它清晰展示了C#依赖注入和手动解析依赖的核心机制。
在实际项目中,建议使用成熟的DI框架(如Microsoft.Extensions.DependencyInjection、Autofac等),但掌握底层原理能让你更好地利用这些工具,并在必要时进行定制化开发。
记住,控制反转(IoC)是思想,依赖注入(DI)是实现方式之一。理解它们,你将写出更优雅、更灵活的C#代码!
本文由主机测评网于2025-12-22发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20251211413.html