从依赖倒置原则到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容器和依赖注入的基本概念

相关推荐
大黄说说6 小时前
.NET 10 Minimal APIs 主要应用场景全景指南:从原型到企业级生产
.net
专注VB编程开发20年7 小时前
c# vb.net Redis 左侧添加,右侧添加(添加到头部,添加到尾部)
redis·c#·.net
专注VB编程开发20年13 小时前
c#,vb.net Redis vs ODBC/ADO 查库的速度差距,写入json数据和字典数据
redis·c#·.net
大鹏说大话14 小时前
基于.NET和C#构建光伏IoT物模型方案:架构设计与实践指南
物联网·c#·.net
专注VB编程开发20年1 天前
流式解压 + 分块处理 + 增量安装
.net
guizhoumen2 天前
liunx环境手动安装.net8的教程
.net
全栈小53 天前
【C#】.net 6.0和8.0有什么区别,以及8.0增加了那些功能,这些功能有那些作用
开发语言·c#·.net
qq_297908013 天前
C#印刷线路板ERP进销存报价财务库存贸易生产企业管理系统软件
sqlserver·开源·c#·.net·开源软件
专注VB编程开发20年3 天前
WebView2 处理跨域访问限制,Frame脚本执行,难度比CEF大10倍
前端·javascript·.net
weixin_421994784 天前
基于 .NET 9.0 的高性能轻量级令牌桶限流服务
.net·.netcore·令牌桶