既然了解了IL的接口和动态类之间的知识,何不使用进来项目实验一下呢?而第一反应就是想到了平时经常说的IOC容器,在园子里搜索了一下也有这类型的文章http://www.cnblogs.com/kklldog/p/3395641.html,借鉴一下前人的知识就来实现一下吧。IOC的概念就不介绍了,想了解的同学就百度一下。

一、定义接口

首先自定义两个接口和实现

    public interface IAnimal
    {
        string Cat();

        string Dog();
    }

    public class Animal:IAnimal
    {
        public string Cat()
        {
            return "I Am Cat";
        }

        public string Dog()
        {
            return "I Am Dog";
        }
    }

IAnimal

    public interface IMail
    {
        string SendMail();

        string ReceiveMail();
    }

    public class Mail:IMail
    {
        public string SendMail()
        {
            return "Success Send";
        }

        public string ReceiveMail()
        {
            return "Success Receive";
        }
    }

IMail

二、配置

这里我就直接写一个方法来进行配置,不再定义接口了

        public Dictionary<string,string> GetAllConfig()
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("IOC.Interface.IMail", "IOC.Interface.Mail,IOC");
            dic.Add("IOC.Interface.IAnimal", "IOC.Interface.Animal,IOC");
            return dic;
        }

Config

三、反射实现

        public static object GetInstance(string InterfaceName)
        {
            //已经存在的对象直接使用
            if (dicObj.ContainsKey(InterfaceName))
            {
                return dicObj[InterfaceName];
            }

            var dicConfig = new Config.Config().GetAllConfig();
            if (!dicConfig.ContainsKey(InterfaceName))
            {
                throw new Exception("未配置");
            }
            var config = dicConfig[InterfaceName];

            Type taskType = Type.GetType(config);

           // var taskObj1 = CreateInstance(taskType);
            var taskObj= CreateInstanceByEmit(taskType);

            if (null == taskObj)
                throw new Exception("实例化接口错误");

            dicObj.Add(InterfaceName, taskObj);
            return taskObj;
        }

GetInstance

        private static Object CreateInstance(Type taskType)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();

            object taskObj = Activator.CreateInstance(taskType);
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;

            string elapsedTime = String.Format("{0}",ts.Ticks );
            Console.WriteLine("CreateInstance RunTime " + elapsedTime);
            return taskObj;
        }

CreateInstance

通过传入接口,再去配置列表中找到对应的实现进行实例化。如果存在就直接使用实例化后的对象

四、Emit实现

要想知道Emit是如何获取接口对应实例化的对象,可以先进行一下的尝试。比如我要获取IAnimal接口实例化的对象

        public IAnimal GetInterface()
        {
            var realize= new Animal();
            return (IAnimal)realize;
        }

通过反编译工具得到以下的IL信息

IL解释:

L_0001:创建一个新的对象(构造函数)到计算堆栈上

L_0006-L_0007:先存储到指定位置再获取推送到计算堆栈上(实现中可省略)

L_0008-L_000b:同样是先存储到指定位置再获取推送到堆栈上(实现中可省略),br.s跳转到L_000b执行(针对这段IL没必要用到这个操作)

L_000c:返回

然后我们可以通过IL代码进行实现

        private static Object CreateInstanceByEmit(Type taskType)
        {
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            BindingFlags defaultFlags = BindingFlags.Public | BindingFlags.Instance;
            ];//获取默认构造函数

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString("N"), typeof(Object), new[] { typeof(object[]) }, true);
            ILGenerator IL = dynamicMethod.GetILGenerator();
            IL.Emit(OpCodes.Newobj, constructor);
            if (constructor.ReflectedType.IsValueType)
                IL.Emit(OpCodes.Box, constructor.ReflectedType);
            IL.Emit(OpCodes.Ret);
            //关联方法
            var func = (Func<Object>)dynamicMethod.CreateDelegate(typeof(Func<Object>));

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0}", ts.Ticks);
            Console.WriteLine("CreateInstanceByEmit RunTime " + elapsedTime);

            return func.Invoke();
        }

CreateInstanceByEmit

五、执行

IAnimal iMail = ServiceTaker.GetService<IOC.Interface.IAnimal>();
Console.WriteLine(iMail.Cat());

通过以上的例子算是对Emit加深一下了解,也可以了解一下IOC的实现,当然IOC还有其他东西需要注意这就不一一介绍了。有兴趣的欢迎来进行交流

源码:IOC

=============================================================

在实例化对象过程中,发现反射执行的速度还是优于Emit的,在参考http://kb.cnblogs.com/page/171668/发现反射和Emit对比在性能上也还是有差距的。这部分了解后再分享~~~

IL实现简单的IOC容器的更多相关文章

  1. IoC原理-使用反射/Emit来实现一个最简单的IoC容器

    从Unity到Spring.Net,到Ninject,几年来陆陆续续用过几个IoC框架.虽然会用,但也没有一直仔细的研究过IoC实现的过程.最近花了点时间,下了Ninject的源码,研究了一番,颇有收 ...

  2. 【最简单IOC容器实现】实现一个最简单的IOC容器

    前面DebugLZQ的两篇博文: 浅谈IOC--说清楚IOC是什么 IoC Container Benchmark - Performance comparison 在浅谈IOC--说清楚IOC是什么 ...

  3. 比Spring简单的IoC容器

    比Spring简单的IoC容器 Spring 虽然比起EJB轻量了许多,但是因为它需要兼容许多不同的类库,导致现在Spring还是相当的庞大的,动不动就上40MB的jar包, 而且想要理解Spring ...

  4. 几句代码简单实现IoC容器

    前言 最近在调试EasyNetQ代码的时候发现里面有一段代码,就是IoC容器的简单实现,跟着他的代码敲了一遍,发现了奇妙之处.当然也是因为我才疏学浅导致孤陋寡闻了.他的思路就是通过动态调用构造函数生成 ...

  5. 手写一个最简单的IOC容器,从而了解spring的核心原理

    从事开发工作多年,spring源码没有特意去看过.但是相关技术原理倒是背了不少,毕竟面试的那关还是得过啊! 正所谓面试造火箭,工作拧螺丝.下面实现一个最简单的ioc容器,供大家参考. 1.最终结果 2 ...

  6. .NET实现一个简单的IOC容器

    目录 1.主要细节 2.具体示例 参考及示例代码下载 shanzm-2020年3月17日 20:06:01 1.主要细节 使用反射程序集的方式获取对象的类型 通过反射的方式获取指定类型的的所有公共属性 ...

  7. 自己动手实现一个简单的 IOC容器

    控制反转,即Inversion of Control(IoC),是面向对象中的一种设计原则,可以用有效降低架构代码的耦合度,从对象调用者角度又叫做依赖注入,即Dependency Injection( ...

  8. 最简单的ioc容器代码(低仿Spring )

    Spring 的一大核心就是IOC,控制反转(依赖注入). 对象交由容器去控制,降低耦合性. Spring 的ioc实现原理其实很简单,容器启动后读取并解析配置文件,根据配置文件中<bean&g ...

  9. 简单模拟IOC容器:返回对象并能抛出异常

    本次要求:已知com.zzj.vo包下分别有Tiger.lion.Elephant三个Java源文件,请据此实现以下功能:①.自定义一个名为Component的注解,要求该注解只能用于类且代码运行时该 ...

随机推荐

  1. JavaScript权威指南 - 对象

    JavaScript对象可以看作是属性的无序集合,每个属性就是一个键值对,可增可删. JavaScript中的所有事物都是对象:字符串.数字.数组.日期,等等. JavaScript对象除了可以保持自 ...

  2. 第一个移动前端开源项目-dailog

    你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...

  3. angular 源码分析 1 - angularInit()

    angularjs 是个神奇的框架,由于我的好奇,想了解她的内部工作原理,只能一步一步的走进她,靠近她,和她深入的交流. angularjs 的入口是什么样子的呢?一起掀起她的盖头吧. 在这里我只讲方 ...

  4. ComponentPattern (组合模式)

    import java.util.LinkedList; /** * 组合模式 * * @author TMAC-J 主要用于树状结构,用于部分和整体区别无区别的场景 想象一下,假设有一批连锁的理发店 ...

  5. 【从零开始学BPM,Day5】报表配置及自定义功能页面开发

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第五天课程] 1.课程概要 Step 1 软件下载:H3 BP ...

  6. 张高兴的 UWP 开发笔记:汉堡菜单进阶

    不同于Windows 8应用,Windows 10引入了"汉堡菜单"这一导航模式.说具体点,就拿官方的天气应用来说,左上角三条横杠的图标外加一个SplitView控件组成的这一导航 ...

  7. 编译器开发系列--Ocelot语言1.抽象语法树

    从今天开始研究开发自己的编程语言Ocelot,从<自制编译器>出发,然后再自己不断完善功能并优化. 编译器前端简单,就不深入研究了,直接用现成的一款工具叫JavaCC,它可以生成抽象语法树 ...

  8. git和pycharm管理代码

    首先明白三个概念,服务器代码库,本地代码库,和正在coding的项目. coding完毕后,先通过commit提交到本地代码库,然后通过push再提交server的代码库    git步骤 git c ...

  9. Microsoft Visual Studio 2017 for Mac Preview 下载+安装+案例Demo

    目录: 0. 前言 1. 在线安装器 2. 安装VS 3. HelloWorld 4. ASP.NET MVC 5. 软件下载 6. 结尾 0. 前言: 工作原因,上下班背着我的雷神,一个月瘦了10斤 ...

  10. PMON failed to acquire latch, see PMON dump

    前几天,一台Oracle数据库(Oracle Database 10g Release 10.2.0.4.0 - 64bit Production)监控出现"PMON failed to a ...