先看看 IoC百度百科

优化过程

  1. namespace Test
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. //场景 某公司客服要回访一些客户
  8. //刚开始 回访的方式只有 打电话
  9. //简单的实现
  10. CustomerService1 cs1 = new CustomerService1();
  11. cs1.Call();
  12. }
  13. }
  14. public class CustomerService1
  15. {
  16. public string Call()
  17. {
  18. return "打电话";
  19. }
  20. }
  21. }
  1. namespace Test
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. //后来又添加了发短信的回访方式
  8. //考虑到以后还可能增加回访方式
  9. //而且为了不改动Main函数代码 我们将封装回访方法
  10. //但是这样只是将回访方式将造成的改动下移到了 Customer2里面了
  11. //然后将回访方式的选择放到配置文件appconfig里面 用户可以设置默认的回访方式
  12. CustomerService2 cs2 = new CustomerService2();
  13. string Method = System.Configuration.ConfigurationManager.AppSettings["Method"];
  14. cs2.Visit(Method);
  15. }
  16. }
  17. public class CustomerService2
  18. {
  19. public string Visit(string Method)
  20. {
  21. string result = "Not Found";
  22. switch (Method)
  23. {
  24. case "Call":
  25. result = Call();
  26. break;
  27. case "SMS":
  28. result = SMS();
  29. break;
  30. }
  31. return result;
  32. }
  33. private string Call()
  34. {
  35. return "打电话";
  36. }
  37. private string SMS()
  38. {
  39. return "发短信";
  40. }
  41. }
  42. }
  1. namespace Test
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. string Method = System.Configuration.ConfigurationManager.AppSettings["Method"];
  8.  
  9. //下来我们继续减少功能变化造成的代码修改
  10. //如果增加功能虽然Main不用更改但是CustomerService2还是得改动
  11. //我们接下来继续优化CustomerService
  12. //见CustomerService3 内部注释 Main已经不需改动
  13. CustomerService3 cs3 = new CustomerService3();
  14. cs3.Visit(Method);
  15. }
  16. }
  17. public class CustomerService3
  18. {
  19. public string Visit(string Method)
  20. {
  21. //参照CustomerService2可以发现如果 添加回访方式 就必须在Visit的Switch里面加一个case 再加一功能方法
  22. //我们先分离这些方法
  23. //将他们接口化
  24. //可以发现方法的实现被抽象出来了
  25. //进一步用户swith请看 CustomerService4
  26. IServiceMethod servicemethod = null;
  27. switch (Method)
  28. {
  29. case "Call":
  30. servicemethod = new CallMethod();
  31. break;
  32. case "SMS":
  33. servicemethod = new SMSMethod();
  34. break;
  35. }
  36. return servicemethod.Vist();
  37. }
  38. }
  39. public class CallMethod
  40. {
  41. public string Vist()
  42. {
  43. return "打电话";
  44. }
  45. }
  46. public class SMSMethod
  47. {
  48. public string Vist()
  49. {
  50. return "发短信";
  51. }
  52. }
  53. }
  1. namespace Test
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. string Method = System.Configuration.ConfigurationManager.AppSettings["Method"];
  8.  
  9. CustomerSerive4 cs4 = new CustomerSerive4();
  10. cs4.Visit(Method);
  11. }
  12. }
  13.  
  14. public class CustomerSerive4
  15. {
  16. public string Visit(string Method)
  17. {
  18. //为了根据Method来实例化方法 并进行调用 我们需要引入 反射机制
  19. //根据我们原来的命令规范 Method参数+"Method"就是我们需要找的类 由于在我们在同一个程序集里面 所以可以直接用Test 后面考虑建一个映射配置来查找
  20. //这样我们就把回访方式的增加带来的代码的更改 从Main下放到了CustomerService 又从CustomerService下方到了IServiceMetod的实现类中
  21. //最后一步就是将IServiceMethod实现类的增加带来项目的重新生成dll的重新编译 重新发布问题了
  22. //请看 CustomerService5
  23. IServiceMethod servicemethod = Activator.CreateInstance("Test", Method + "Method") as IServiceMethod;
  24. return servicemethod.Vist();
  25. }
  26. }
  27. public interface IServiceMethod
  28. {
  29. string Vist();
  30. }
  31. public class CallMethod : IServiceMethod
  32. {
  33. public string Vist()
  34. {
  35. return "打电话";
  36. }
  37. }
  38. public class SMSMethod : IServiceMethod
  39. {
  40. public string Vist()
  41. {
  42. return "发短信";
  43. }
  44. }
  45. }
  1. namespace Test
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. string Method = System.Configuration.ConfigurationManager.AppSettings["Method"];
  8.  
  9. CustomerService5 cs5 = new CustomerService5();
  10. cs5.Visit(Method);
  11.  
  12. }
  13. }
  14. public class CustomerService5
  15. {
  16. public string Visit(string Method)
  17. {
  18. //解决重新编译的方法就是
  19. //1.将IServiceMetod接口独立成一个项目 另一个名称空间 使之独立存在 注意此处 IServiceMetod是TestInterface名称空间(TestInterface.dll里面)
  20. //2.将CallMethod、SMSMethod等IServiceMetod接口的实现类也独立成一个项目TestMethodImp (TestMethodImp.dll)里面
  21. TestMethodInterface.IServiceMethod servicemethod = Activator.CreateInstance("TestMethodImp", Method+"Method") as TestMethodInterface.IServiceMethod;
  22. return servicemethod.Vist();
  23. }
  24. }
  25.  
  26. public interface IServiceMethod
  27. {
  28. string Vist();
  29. }
  30. public class CallMethod : IServiceMethod
  31. {
  32. public string Vist()
  33. {
  34. return "打电话";
  35. }
  36. }
  37. public class SMSMethod : IServiceMethod
  38. {
  39. public string Vist()
  40. {
  41. return "发短信";
  42. }
  43. }
  44.  
  45. }
  46.  
  47. namespace TestMethodInterface
  48. {
  49. public interface IServiceMethod
  50. {
  51. string Vist();
  52. }
  53. }
  54. namespace TestMethodImp
  55. {
  56. public class CallMethod : TestMethodInterface.IServiceMethod
  57. {
  58. public string Vist()
  59. {
  60. return "打电话";
  61. }
  62. }
  63. public class SMSMethod : TestMethodInterface.IServiceMethod
  64. {
  65. public string Vist()
  66. {
  67. return "发短信";
  68. }
  69. }
  70. }

框架后

主要方法

  1. /// <summary>
  2. /// 创建对象
  3. /// </summary>
  4. /// <typeparam name="T">对象类型</typeparam>
  5. /// <param name="Key">对象关键字</param>
  6. public static T CreateStance<T>(string Key)
  7.  
  8. /// <summary>
  9. /// 创建一个对象 单例模式
  10. /// </summary>
  11. /// <typeparam name="T">对象类型</typeparam>
  12. /// <param name="Key">对象关键字</param>
  13. public static T CreateSingle<T>(string Key)

xml配置

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <IoCMap>
  3. <Map>
  4. <Key>Data</Key>
  5. <Value>Test_Business.Data</Value>
  6. </Map>
  7. <Map>
  8. <Key>Main</Key>
  9. <Value>Test_Business.Main</Value>
  10. </Map>
  11. <Map>
  12. <Key>Data2</Key>
  13. <Value>Test_Business2.Data</Value>
  14. </Map>
  15. <Map>
  16. <Key>Main2</Key>
  17. <Value>Test_Business2.Main</Value>
  18. </Map>
  19. </IoCMap>

 实现主要代码

  1. Assembly.CreateInstance(ObejctName);
  2. Assembly.LoadFrom(AssemblePath);

实战使用

第一步:创建接口

  1. /// <summary>
  2. /// 数据接口
  3. /// </summary>
  4. public interface IData
  5. {
  6. /// <summary>
  7. /// 数据
  8. /// </summary>
  9. string DataString { get; set; }
  10. }
  11.  
  12. /// <summary>
  13. /// 程序运行接口
  14. /// </summary>
  15. public interface IMain
  16. {
  17. /// <summary>
  18. /// 处理方法
  19. /// </summary>
  20. /// <param name="data">数据类型</param>
  21. string ProcData(IData data);
  22. }

第二部:创建两个不同程序集的实现类

  1. /// <summary>
  2. /// 程序运行接口实现类一号
  3. /// </summary>
  4. public class Main : Test_InterFace.IMain
  5. {
  6. /// <summary>
  7. /// 处理方法实现
  8. /// </summary>
  9. public string ProcData(Test_InterFace.IData data)
  10. {
  11. return "我是一号处理方法" + data.DataString;
  12. }
  13. }
  14. /// <summary>
  15. /// 数据实现类一号
  16. /// </summary>
  17. public class Data : Test_InterFace.IData
  18. {
  19. private string _datastring;
  20. /// <summary>
  21. /// 实现数据属性
  22. /// </summary>
  23. public string DataString
  24. {
  25. get
  26. {
  27. return _datastring;
  28. }
  29. set
  30. {
  31. _datastring = "我是数据一号" + value;
  32. }
  33. }
  34. }

2.

  1. /// <summary>
  2. /// 程序运行接口实现类二号
  3. /// </summary>
  4. public class Main2:IMain
  5. {
  6. /// <summary>
  7. /// 处理方法实现
  8. /// </summary>
  9. public string ProcData(IData data)
  10. {
  11. return "我是二号处理方法" + data.DataString;
  12. }
  13. }
  14. /// <summary>
  15. /// 数据实现类二号
  16. /// </summary>
  17. public class Data2:IData
  18. {
  19. private string _dataString;
  20. /// <summary>
  21. /// 实现数据属性
  22. /// </summary>
  23. public string DataString
  24. {
  25. get
  26. {
  27. return _dataString;
  28. }
  29. set
  30. {
  31. _dataString = "我是数据二号" + value;
  32. }
  33. }
  34. }

第三部:写配置

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <IoCMap>
  3. <Map>
  4. <Key>Data</Key>
  5. <Value>Test_Business.Data</Value>
  6. </Map>
  7. <Map>
  8. <Key>Main</Key>
  9. <Value>Test_Business.Main</Value>
  10. </Map>
  11. <Map>
  12. <Key>Data2</Key>
  13. <Value>Test_Business2.Data2</Value>
  14. </Map>
  15. <Map>
  16. <Key>Main2</Key>
  17. <Value>Test_Business2.Main2</Value>
  18. </Map>
  19. </IoCMap>

第四部:开始调用

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. IMain main = IoCFactory.CreateStance<IMain>("Main");
  6. IData data = IoCFactory.CreateSingle<IData>("Data");
  7. Console.WriteLine(main.ProcData(data));
  8. Console.ReadKey();
  9. }
  10. }

运行结果:

更改配置:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <IoCMap>
  3. <Map>
  4. <Key>Data</Key>
  5. <Value>Test_Business2.Data2</Value>
  6. </Map>
  7. <Map>
  8. <Key>Main</Key>
  9. <Value>Test_Business2.Main2</Value>
  10. </Map>
  11. <Map>
  12. <Key>Data2</Key>
  13. <Value>Test_Business.Data</Value>
  14. </Map>
  15. <Map>
  16. <Key>Main2</Key>
  17. <Value>Test_Business.Main</Value>
  18. </Map>
  19. </IoCMap>

结果:

以后的扩展只需引用接口 实现接口 放到程序的bin目录 就可以了

欢迎大牛指点、吐槽。

需要完整代码的留言 O(∩_∩)O谢谢 

自己动手写框架——IoC的实现的更多相关文章

  1. 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan(四)

    功能说明 该步骤实现的功能包括: 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面. 2. 通过ApplicatoinContext的getBean()方法获得容器里面 ...

  2. 一起写框架-Ioc内核容器的实现-基础API的定义(三)

    Ioc内核要解决的问题 1.被调用方,在程序启动时就要创建好对象,放在一个容器里面. 2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象. 解决这个两个问题的思路 1.定义一个对象 ...

  3. 一起写框架-Ioc内核容器的实现-基础功能-容器对象名默认首字母小写(八)

    实现功能 --前面实现的代码-- 默认的对象名就类名.不符合Java的命名规范.我们希望默认的对象名首字母小写. 实现思路 创建一个命名规则的帮助类.实现将对大写开头的对象名修改为小写开头. 实现步骤 ...

  4. 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)

    实现功能 以上的代码我们发现.我们都是将@ComponentScan扫描的路径下的所有类都加载到容器中的. 而实际需求,我们并不希望所有的类都创建对象,而是加了组件注解@Controller,@Ser ...

  5. 一起写框架-Ioc内核容器的实现-基础功能-getBean(五)

    实现的功能 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面.(查看上一篇文) 2. 通过ApplicatoinContext的getBean()方法获得容器里面的对象 ...

  6. 《自己动手写框架2》:用200行的DBF解析器来展示良好架构设计

    因为工作关系.须要工作其中,须要读取DBF文件.找了一些DBF读取开源软件,要么是太过庞大,动不动就上万行.要么是功能有问题,编码,长度,总之是没有找到一个很爽的. 在万般无奈之下,我老人家怒从心头起 ...

  7. 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持多包扫描(六)

    实现功能 1.我们看到@ComponentScan注解一个开始定义就是需要支持,扫描多个包,将多个包的类名获取到.现在就实现这个功能. 实现思路 根据传入的字符串数组,获得多个包下的类全限制名. 实现 ...

  8. 自己动手写Spring框架--IOC、MVC

    对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...

  9. 自己动手实现Spring IoC框架

    钻研Spring 源码也有一段时间了,对Spring IoC的实现原理理解算是比较透彻了,要实现一款IoC容器,简单的概括无非需要以下几个步骤: 1.定义用来描述bean的配置的Java类,例如我们有 ...

随机推荐

  1. poj Building a Space Station

    http://poj.org/problem?id=2031 #include<cstdio> #include<cstring> #include<cmath> ...

  2. android 多线程断点续传下载

    今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...

  3. 基于Minifilter框架的文件过滤驱动理解

    概述 Minifilter即File System Minifilter Drivers,是Windows为了简化第三方开发人员开发文件过滤驱动而提供的一套框架,这个框架依赖于一个称之为Filter ...

  4. 《Linear Algebra and Its Applications》-chaper2-矩阵的逆

    矩阵的逆: 逆矩阵的定义: 类比于我们在研究实数的时候回去讨论一个数的倒数,对应的,在矩阵运算中,当AB = I的时候,A,B互称为逆矩阵,这里的I类似实数中的1,表示单位矩阵,即对角线是1其余位置是 ...

  5. Demon_游戏登录界面(具备账号密码输入功能)

    using UnityEngine; using System.Collections; using UnityEngine.UI;// public class LoginButton : Mono ...

  6. 使用EMOJI表情

    因为IOS系统支持日文中的字块编码,所以在UILable,UITextField,UIAlertView等控件中使用emoji表情编码(emoji就是表情符号:词义来自日语(えもじ,e-moji,mo ...

  7. QP01 BAPI、QP02 BDC

    近期在改动一个检验计划分配的一个程序.上网查了一些资料,分别对QP01检验计划创建.改动QP02.删除物料等操作.分享一下. 一.QP01 BAPI BAPI_INSPECTIONPLAN_CREAT ...

  8. RESTful Web Services: A Tutorial--reference

    As REST has become the default for most Web and mobile apps, it's imperative to have the basics at y ...

  9. Java基础知识强化80:Math类random()方法的小扩展(控制产生目的数字的概率)

    1. Math.random()方法: Math.random()出现的数据是0.0<= x < 1.0之间,随机出现一个数据Math.random()>0.1概率是0.9 那么如下 ...

  10. SpringMVC06以对象的方式获取前台的数据

    ========创建需要的两个实体类================ public class School { private String sName; private String addres ...