剖析一款实现IOC的.NET框架

IOC的含义在百度百科中这样解释:

是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

https://baike.baidu.com/item/%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC/1158025?fr=aladdin

前些年,自己接触到了一款IOC类型的.NET框架,近日,自己对这款框架做些技术分析,并根据其技术特点一个小例子。以期能有新的收获。

首先,大体上介绍下框架背景。

这款框架诞生于本公司,是许多年前公司的架构师做的1.0版本,这个版本最大的特点是使用IOC技术,实现了类似java的编码风格。这款框架的关键点在于怎样实现IOC,这是这款框架的灵魂,也是其价值所在。使用这款框架的项目分2部分,web前端,包含html和controller;后端使用wcf实现了service服务,而后端正是IOC发挥作用的关键环节。

根据框架特点,自己做了一个小例子,如所示:

1.基础类

基础类的作用是作为注入的起点

public static class InjectBizObject
    {
        public static void Inject(Object target)
        {
            Type t = target.GetType();
                
            var fields = t.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public);
            List<FieldInfo> targetFieldInfos = new List<FieldInfo>();
            foreach (var item in fields)
            {
                var fieldType = item.FieldType;
                if (fieldType.IsSubclassOf(typeof(baseClass)))
                {
                    item.SetValue(target, b1.Get(item.FieldType));
                } 
            }
        }
        public static bool IsGenericSubclassOf(Type type, Type superType)
        {
            return type.BaseType.IsSubclassOf(superType);
        }


    }
 public abstract class baseClass
    {
        public void Inject()
        {
            InjectBizObject.Inject(this);
        }
    }

注意:这里的InjectBizObject方法调用了工具类,而工具类(后面提到)也会调用这个工具类,从而用递归方法实现了类->子类->...的实例化。

public class b1
    {
        public static object Get(Type t)
        {
            Object o = null;
            Assembly asm = null;


            asm = t.Assembly;
            o = asm.CreateInstance(t.FullName,
                false,
                BindingFlags.Default | BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
                null,
                null,
                null,
                null);
            
            //获得注入方法,并进行注入
            MethodInfo injectMethod = t.GetMethod("Inject");
            if (injectMethod != null)
            {
                injectMethod.Invoke(o, null);
            }
            return o;
        }
    }
public class Class1: baseClass
    {
        private Class2 _class2;

        public string mm() {
            return _class2.z();
        }
    }
 public class Class2: baseClass
    {

        private string xx = "";
        public string z() {
            return "sdfsdf"+ class3.x();
        }
    }

这里的class1引用了class2,而class2也可以引用其他的类,但为了简便起见,这里引用到class2即可。

下面是程序调用的起点:

Type t = typeof(Class1);

Class1 c = b1.Get(t) as Class1;

string sdfsd = c.mm();

最终,实现class1实例化的同时,其字段class2也会被实例化,一直到找不到继承baseClass的类为止。

点评

感觉框架的作者,研究过的东西挺多,非常理解ioc的用途。但是,对于自己来说,却非常不同意框架的做法,理由如下:

1.破坏了.net的垃圾回收机制。人家.NET Framework的本意是:趁着服务器还有资源,你快申请资源,使用完资源,请交给.NET Framework去处理善后工作,或被回收,或被重用都行。但是你用这套东西,不管是经常用的资源,还是偶尔使用一次的资源,这些资源牢牢被抓在自己手里,而.NET Framework得到的回复始终是:我正在使用,请不要释放我的资源!

2.使用反射技术创建对象实例,效率是何等地低下,如果偶尔几个这样做还行,倘若无论对象大小,和多少,都采用这种方式生成实例,其效率是多么低下,系统的吞吐量会极大降低,系统的资源占用将因为偶尔的一次调用,而永远无法得到释放。

3.没有体现出方便性。做了一圈封装,仅仅就是为了少写class a = new class();这些语句,有点得不偿失。

总之,有点卖弄技术,过度封装的意思。本来一个高度智能化、自动化的框架,因这个八股文般的规定,搞得只能带着手铐脚镣跳舞,悲哉悲哉!

上一篇:C# 获得串口句柄,供 Win32 API 使用


下一篇:c#反射入门篇(Reflection)——MethodInfo 发现方法的属性