从依赖倒置原则到IOC控制反转实现 从手写工厂+配置文件+反射到DI依赖注入实现 手写IOC容器,递归完成构造函数注入

依赖倒置原则(DIP)是面向对象设计(OOD)中的一个重要原则,它提倡:

  1. 高级模块不应该依赖于低级模块,两者都应该依赖于抽象。
  2. 抽象不应该依赖于细节,细节应该依赖于抽象。

这个原则有助于减少类之间的耦合度,使得系统更加灵活、可扩展。

控制反转(IoC)是实现依赖倒置原则的一种技术,它将原本由代码直接操控的对象的调用权交给第三方(比如一个容器)来控制,以解耦代码。IoC的一个常见实现方式是依赖注入(DI),它通常有三种注入方式:构造函数注入、属性注入和方法注入。

在C#中,我们可以通过反射机制,配置文件和工厂模式来手动实现一个简单的IoC容器,以支持构造函数注入。下面是一个简单的示例:

  1. 定义一个接口和它的实现类:
csharp 复制代码
csharp
public interface IService  
{  
    void DoWork();  
}  
  
public class Service : IService  
{  
    private readonly IDependency _dependency;  
  
    public Service(IDependency dependency)  
    {  
        _dependency = dependency;  
    }  
  
    public void DoWork()  
    {  
        _dependency.Help();  
    }  
}  
  
public interface IDependency  
{  
    void Help();  
}  
  
public class Dependency : IDependency  
{  
    public void Help()  
    {  
        Console.WriteLine("Helping...");  
    }  
}
  1. 创建一个简单的配置文件(比如使用XML),用于定义接口和实现类的映射关系:
xml 复制代码
xml
<configuration>  
  <appSettings>  
    <add key="IService" value="YourNamespace.Service, YourAssembly" />  
    <add key="IDependency" value="YourNamespace.Dependency, YourAssembly" />  
  </appSettings>  
</configuration>
  1. 创建一个工厂类,用于读取配置文件并使用反射来创建实例:
csharp 复制代码
csharp
public static class SimpleIoCContainer  
{  
    public static T Resolve<T>()  
    {  
        string typeName = ConfigurationManager.AppSettings[typeof(T).FullName];  
        if (string.IsNullOrEmpty(typeName))  
            throw new InvalidOperationException($"No type registered for {typeof(T).FullName}");  
  
        string[] typeParts = typeName.Split(',');  
        string assemblyName = typeParts[1].Trim();  
        string className = typeParts[0].Trim();  
  
        Type type = Type.GetType($"{className},{assemblyName}");  
        if (type == null)  
            throw new InvalidOperationException($"Type {className} not found in assembly {assemblyName}");  
  
        ConstructorInfo constructor = type.GetConstructors()[0]; // Assuming there is a parameterless constructor or a constructor with resolvable dependencies.  
        ParameterInfo[] parameters = constructor.GetParameters();  
        object[] parameterInstances = new object[parameters.Length];  
  
        for (int i = 0; i < parameters.Length; i++)  
        {  
            parameterInstances[i] = Resolve(parameters[i].ParameterType); // Recursively resolve dependencies.  
        }  
  
        return (T)constructor.Invoke(parameterInstances);  
    }  
  
    // Note: The above code assumes all dependencies can be resolved recursively.   
    // In a real-world scenario, you would need to handle cases where there are circular dependencies or unregistered types.  
    // Additionally, the code does not cache resolved instances, which could lead to performance issues in larger applications.  
    // A fully-fledged IoC container like Autofac, Ninject, or Microsoft.Extensions.DependencyInjection would handle these cases more elegantly.  
}

注意 :上面的SimpleIoCContainer实现非常简化,并且存在几个问题:

  • 它没有处理循环依赖的情况。
  • 它没有缓存已解析的实例,这可能导致性能问题。
  • 它假设配置文件中总是存在正确的映射,并且构造函数参数总是可以解析的。在实际应用中,这些情况都需要更加健壮的处理。
  • 它没有考虑到生命周期管理(如单例、每次请求、每次调用等)。
  • 它使用ConfigurationManager.AppSettings来读取配置,这在.NET Core和.NET 5+中不是推荐的做法;应使用Microsoft.Extensions.Configuration代替。
  • 没有错误处理机制来处理例如类型未找到或构造函数调用失败等异常情况。在实际应用中,应添加适当的错误处理逻辑。

在实际项目中,建议使用成熟的IoC容器库(如Autofac、Ninject、Unity或Microsoft.Extensions.DependencyInjection),因为它们提供了更多的功能、更好的性能和更少的潜在问题。上面的示例仅用于教学目的,以演示IoC容器和依赖注入的基本概念

相关推荐
内核程序员kevin4 小时前
在Linux环境下使用Docker打包和发布.NET程序并配合MySQL部署
linux·mysql·docker·.net
qtvb19879 小时前
机器视觉中常用图像处理库都有哪些?重点关注.net
图像处理·人工智能·.net
小码编匠17 小时前
WPF 中文字模糊的问题:TextOptions的用法
后端·c#·.net
界面开发小八哥1 天前
DevExpress中文教程 - 如何使用AI模型检查HTML编辑中的语法?
ai·.net·界面控件·devexpress·ui开发
Net分享2 天前
NET平台超级好用的几款FTP客户端操作库--附代码
后端·.net
Crazy Struggle2 天前
一款 C# 编写的神经网络计算图框架
神经网络·.net·图像处理库
九鼎科技-Leo2 天前
什么是 WPF 中的转换器?如何自定义一个值转换器?
开发语言·windows·c#·.net·wpf
为风而战2 天前
Deepin 系统中安装Rider和Uno Platform
linux·运维·.net·wpf
九鼎科技-Leo2 天前
在 WPF 中,绑定机制是如何工作的?WPF数据绑定机制解析
windows·c#·.net·wpf
VinciYan3 天前
.NET使用SqlSugar实现单列批量更新的几种实现和对比
数据库·c#·asp.net·.net·.netcore