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

相关推荐
Kookoos1 小时前
Redis + ABP vNext 构建分布式高可用缓存架构
redis·分布式·缓存·架构·c#·.net
小乖兽技术5 小时前
在 .NET 8 开发的WinForms 程序中展示程序版本号的几种方式
开发语言·c#·.net
瓜皮弟子头很铁18 小时前
.net 公共变量 线程安全
.net
江沉晚呤时20 小时前
C# 实现雪花算法(Snowflake Algorithm)详解与应用
c#·.net
bicijinlian1 天前
.Net HttpClient 使用代理功能
c#·.net·httpclient·.net httpclient·httpclient 代理
界面开发小八哥2 天前
界面控件DevExpress WinForms v24.2 - 数据处理功能增强
.net·界面控件·devexpress·ui开发·winforms
码观天工2 天前
【.NET必读】RabbitMQ 4.0+重大变更!C#开发者必须掌握的6大升级要点
c#·rabbitmq·.net·mq
o0向阳而生0o2 天前
43、Server.UrlEncode、HttpUtility.UrlDecode的区别?
c#·.net
Kookoos2 天前
【实战】基于 ABP vNext 构建高可用 S7 协议采集平台(西门子 PLC 通信全流程)
后端·物联网·c#·.net
焚 城3 天前
.NET8关于ORM的一次思考
后端·.net