.net core反射练习-简易版IOC容器实现

Posted exxxxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.net core反射练习-简易版IOC容器实现相关的知识,希望对你有一定的参考价值。

实现一个简易的IOC容器

先说一下简单思路,参考ServiceCollection,需要一个注册方法跟获取实例方法,同时支持构造函数注入。那么只需要一个地方存储注册接口跟该接口的继承类,以及根据类的构造函数去实例化一个对象出来。

创建一个.net core控制台程序,新建一个Container类。

创建一个静态字典存储类以及对应的type,这就是存储注册接口的地方

static Dictionary<string, Type> typeDic = new Dictionary<string, Type>();

然后就是实例化对象方法

        /// <summary>
        /// 根据类型实例化对象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public T GetService<T>()
        
            var type = typeof(T);
            var targetType = typeDic[type.FullName];

            return (T)Activator.CreateInstance(targetType);
        

很简单的一个方法,也有很明显的缺陷,不过现在已经可以根据注册的接口来实例化一个类。

最明显的一个问题是,没有根据构造函数来实例化类,下面来进行改进:

        /// <summary>
        /// 根据类型实例化对象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public object CreateInstance(Type type)
        
            object result = new object();
            var targetType = typeDic[type.FullName];
       var ctor = targetType.GetConstructors().OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();

            var paraList = new List<object>();
            if (ctor != null)
            
                foreach (var para in ctor.GetParameters())
                
                    var paraType = para.ParameterType;
                    var paraInstance = CreateInstance(paraType);
                    paraList.Add(paraInstance);
                
            
            try
            
                result = Activator.CreateInstance(targetType, paraList.ToArray());
            
            catch (Exception ex)
            
                Console.WriteLine(ex.Message);
            
            
            return result;
        

把容器实例化对象的方法独立出来,上面的方法做了两个改进:

  • 默认选取最多参数的构造函数,这也是ServiceCollection的策略
  • 递归构造函数里面的每个参数,为每个参数都进行实例化

再添加一个方法调用该方法给外部使用

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetService<T>()
        
            return (T)CreateInstance(typeof(T));
        

到这里就可以进行测试了,新建一个ISql接口,创建一个查询方法

namespace ISql

    public interface ISqlHelpr
    
        void Query();
    

分别创建两个类继承ISql

using System;
using ISql;

namespace MySqlTest

    public class MySqlHelpr : ISqlHelpr
    
        public void Query()
        
            Console.WriteLine("使用Mysql查询");
        
    
using System;
using ISql;

namespace MySqlServerTest

    public class SqlServerHelper : ISqlHelpr
    
        public void Query()
        
            Console.WriteLine("使用SqlServer查询");
        
    

返回控制台,新建一个容器,注册,获取实例,进行测试:

 

 

 

 

 

 可以看到注册不同的类就实例化了对应的对象实例

下面再创建一个testClass类继承Itest接口,在MySqlHelper类中调用,展示构造函数注入

    public interface Itest
    
        public void consoleTest();
    

    public class testClass : Itest
    
        public void consoleTest()
        
            Console.WriteLine("调用consoleTest");
        
    

修改MySqlHelpr

    public class MySqlHelpr : ISqlHelpr
    
        private readonly Itest _testClass;

        public MySqlHelpr(Itest testClass)
        
            _testClass = testClass;
        

        public void Query()
        
            _testClass.consoleTest();
            Console.WriteLine("使用Mysql查询");
        
    

回到控制台,注册testClass,就可以看到结果

 

 

 done

 

以上是关于.net core反射练习-简易版IOC容器实现的主要内容,如果未能解决你的问题,请参考以下文章

如何手写一个简易版SpringMVC

spring学习总结002 --- IOC容器启动源码(简易版)

手写实现自定义简易版Spring (实现IoC 和 AOP)

手写实现自定义简易版Spring (实现IoC 和 AOP)

手写一个简易的IOC

通过反射实现IOC功能