自己动手写框架——IoC的实现
先看看 IoC百度百科
优化过程
namespace Test { class Program { static void Main(string[] args) { //场景 某公司客服要回访一些客户 //刚开始 回访的方式只有 打电话 //简单的实现 CustomerService1 cs1 = new CustomerService1(); cs1.Call(); } } public class CustomerService1 { public string Call() { return "打电话"; } } }
namespace Test { class Program { static void Main(string[] args) { //后来又添加了发短信的回访方式 //考虑到以后还可能增加回访方式 //而且为了不改动Main函数代码 我们将封装回访方法 //但是这样只是将回访方式将造成的改动下移到了 Customer2里面了 //然后将回访方式的选择放到配置文件appconfig里面 用户可以设置默认的回访方式 CustomerService2 cs2 = new CustomerService2(); string Method = System.Configuration.ConfigurationManager.AppSettings["Method"]; cs2.Visit(Method); } } public class CustomerService2 { public string Visit(string Method) { string result = "Not Found"; switch (Method) { case "Call": result = Call(); break; case "SMS": result = SMS(); break; } return result; } private string Call() { return "打电话"; } private string SMS() { return "发短信"; } } }
namespace Test { class Program { static void Main(string[] args) { string Method = System.Configuration.ConfigurationManager.AppSettings["Method"]; //下来我们继续减少功能变化造成的代码修改 //如果增加功能虽然Main不用更改但是CustomerService2还是得改动 //我们接下来继续优化CustomerService //见CustomerService3 内部注释 Main已经不需改动 CustomerService3 cs3 = new CustomerService3(); cs3.Visit(Method); } } public class CustomerService3 { public string Visit(string Method) { //参照CustomerService2可以发现如果 添加回访方式 就必须在Visit的Switch里面加一个case 再加一功能方法 //我们先分离这些方法 //将他们接口化 //可以发现方法的实现被抽象出来了 //进一步用户swith请看 CustomerService4 IServiceMethod servicemethod = null; switch (Method) { case "Call": servicemethod = new CallMethod(); break; case "SMS": servicemethod = new SMSMethod(); break; } return servicemethod.Vist(); } } public class CallMethod { public string Vist() { return "打电话"; } } public class SMSMethod { public string Vist() { return "发短信"; } } }
namespace Test { class Program { static void Main(string[] args) { string Method = System.Configuration.ConfigurationManager.AppSettings["Method"]; CustomerSerive4 cs4 = new CustomerSerive4(); cs4.Visit(Method); } } public class CustomerSerive4 { public string Visit(string Method) { //为了根据Method来实例化方法 并进行调用 我们需要引入 反射机制 //根据我们原来的命令规范 Method参数+"Method"就是我们需要找的类 由于在我们在同一个程序集里面 所以可以直接用Test 后面考虑建一个映射配置来查找 //这样我们就把回访方式的增加带来的代码的更改 从Main下放到了CustomerService 又从CustomerService下方到了IServiceMetod的实现类中 //最后一步就是将IServiceMethod实现类的增加带来项目的重新生成dll的重新编译 重新发布问题了 //请看 CustomerService5 IServiceMethod servicemethod = Activator.CreateInstance("Test", Method + "Method") as IServiceMethod; return servicemethod.Vist(); } } public interface IServiceMethod { string Vist(); } public class CallMethod : IServiceMethod { public string Vist() { return "打电话"; } } public class SMSMethod : IServiceMethod { public string Vist() { return "发短信"; } } }
namespace Test { class Program { static void Main(string[] args) { string Method = System.Configuration.ConfigurationManager.AppSettings["Method"]; CustomerService5 cs5 = new CustomerService5(); cs5.Visit(Method); } } public class CustomerService5 { public string Visit(string Method) { //解决重新编译的方法就是 //1.将IServiceMetod接口独立成一个项目 另一个名称空间 使之独立存在 注意此处 IServiceMetod是TestInterface名称空间(TestInterface.dll里面) //2.将CallMethod、SMSMethod等IServiceMetod接口的实现类也独立成一个项目TestMethodImp (TestMethodImp.dll)里面 TestMethodInterface.IServiceMethod servicemethod = Activator.CreateInstance("TestMethodImp", Method+"Method") as TestMethodInterface.IServiceMethod; return servicemethod.Vist(); } } public interface IServiceMethod { string Vist(); } public class CallMethod : IServiceMethod { public string Vist() { return "打电话"; } } public class SMSMethod : IServiceMethod { public string Vist() { return "发短信"; } } } namespace TestMethodInterface { public interface IServiceMethod { string Vist(); } } namespace TestMethodImp { public class CallMethod : TestMethodInterface.IServiceMethod { public string Vist() { return "打电话"; } } public class SMSMethod : TestMethodInterface.IServiceMethod { public string Vist() { return "发短信"; } } }
框架后
主要方法:
/// <summary> /// 创建对象 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="Key">对象关键字</param> public static T CreateStance<T>(string Key) /// <summary> /// 创建一个对象 单例模式 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="Key">对象关键字</param> public static T CreateSingle<T>(string Key)
xml配置:
<?xml version="1.0" encoding="utf-8" ?> <IoCMap> <Map> <Key>Data</Key> <Value>Test_Business.Data</Value> </Map> <Map> <Key>Main</Key> <Value>Test_Business.Main</Value> </Map> <Map> <Key>Data2</Key> <Value>Test_Business2.Data</Value> </Map> <Map> <Key>Main2</Key> <Value>Test_Business2.Main</Value> </Map> </IoCMap>
实现主要代码:
Assembly.CreateInstance(ObejctName); Assembly.LoadFrom(AssemblePath);
实战使用:
第一步:创建接口
/// <summary> /// 数据接口 /// </summary> public interface IData { /// <summary> /// 数据 /// </summary> string DataString { get; set; } } /// <summary> /// 程序运行接口 /// </summary> public interface IMain { /// <summary> /// 处理方法 /// </summary> /// <param name="data">数据类型</param> string ProcData(IData data); }
第二部:创建两个不同程序集的实现类
/// <summary> /// 程序运行接口实现类一号 /// </summary> public class Main : Test_InterFace.IMain { /// <summary> /// 处理方法实现 /// </summary> public string ProcData(Test_InterFace.IData data) { return "我是一号处理方法" + data.DataString; } } /// <summary> /// 数据实现类一号 /// </summary> public class Data : Test_InterFace.IData { private string _datastring; /// <summary> /// 实现数据属性 /// </summary> public string DataString { get { return _datastring; } set { _datastring = "我是数据一号" + value; } } }
2.
/// <summary> /// 程序运行接口实现类二号 /// </summary> public class Main2:IMain { /// <summary> /// 处理方法实现 /// </summary> public string ProcData(IData data) { return "我是二号处理方法" + data.DataString; } } /// <summary> /// 数据实现类二号 /// </summary> public class Data2:IData { private string _dataString; /// <summary> /// 实现数据属性 /// </summary> public string DataString { get { return _dataString; } set { _dataString = "我是数据二号" + value; } } }
第三部:写配置
<?xml version="1.0" encoding="utf-8" ?> <IoCMap> <Map> <Key>Data</Key> <Value>Test_Business.Data</Value> </Map> <Map> <Key>Main</Key> <Value>Test_Business.Main</Value> </Map> <Map> <Key>Data2</Key> <Value>Test_Business2.Data2</Value> </Map> <Map> <Key>Main2</Key> <Value>Test_Business2.Main2</Value> </Map> </IoCMap>
第四部:开始调用
class Program { static void Main(string[] args) { IMain main = IoCFactory.CreateStance<IMain>("Main"); IData data = IoCFactory.CreateSingle<IData>("Data"); Console.WriteLine(main.ProcData(data)); Console.ReadKey(); } }
运行结果:
更改配置:
<?xml version="1.0" encoding="utf-8" ?> <IoCMap> <Map> <Key>Data</Key> <Value>Test_Business2.Data2</Value> </Map> <Map> <Key>Main</Key> <Value>Test_Business2.Main2</Value> </Map> <Map> <Key>Data2</Key> <Value>Test_Business.Data</Value> </Map> <Map> <Key>Main2</Key> <Value>Test_Business.Main</Value> </Map> </IoCMap>
结果:
以后的扩展只需引用接口 实现接口 放到程序的bin目录 就可以了
欢迎大牛指点、吐槽。
需要完整代码的留言 O(∩_∩)O谢谢
自己动手写框架——IoC的实现的更多相关文章
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan(四)
功能说明 该步骤实现的功能包括: 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面. 2. 通过ApplicatoinContext的getBean()方法获得容器里面 ...
- 一起写框架-Ioc内核容器的实现-基础API的定义(三)
Ioc内核要解决的问题 1.被调用方,在程序启动时就要创建好对象,放在一个容器里面. 2.调用方使用一个接口或类的引用(不用使用new),就可以创建获得对象. 解决这个两个问题的思路 1.定义一个对象 ...
- 一起写框架-Ioc内核容器的实现-基础功能-容器对象名默认首字母小写(八)
实现功能 --前面实现的代码-- 默认的对象名就类名.不符合Java的命名规范.我们希望默认的对象名首字母小写. 实现思路 创建一个命名规则的帮助类.实现将对大写开头的对象名修改为小写开头. 实现步骤 ...
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持组件注解限制(七)
实现功能 以上的代码我们发现.我们都是将@ComponentScan扫描的路径下的所有类都加载到容器中的. 而实际需求,我们并不希望所有的类都创建对象,而是加了组件注解@Controller,@Ser ...
- 一起写框架-Ioc内核容器的实现-基础功能-getBean(五)
实现的功能 1. 启动程序时,将@ComponentScan加载的类,创建对象并放在容器里面.(查看上一篇文) 2. 通过ApplicatoinContext的getBean()方法获得容器里面的对象 ...
- 《自己动手写框架2》:用200行的DBF解析器来展示良好架构设计
因为工作关系.须要工作其中,须要读取DBF文件.找了一些DBF读取开源软件,要么是太过庞大,动不动就上万行.要么是功能有问题,编码,长度,总之是没有找到一个很爽的. 在万般无奈之下,我老人家怒从心头起 ...
- 一起写框架-Ioc内核容器的实现-基础功能-ComponentScan支持多包扫描(六)
实现功能 1.我们看到@ComponentScan注解一个开始定义就是需要支持,扫描多个包,将多个包的类名获取到.现在就实现这个功能. 实现思路 根据传入的字符串数组,获得多个包下的类全限制名. 实现 ...
- 自己动手写Spring框架--IOC、MVC
对于一名Java开发人员,我相信没有人不知道 Spring 框架,而且也能够轻松就说出 Spring 的特性-- IOC.MVC.AOP.ORM(batis). 下面我想简单介绍一下我写的轻量级的 S ...
- 自己动手实现Spring IoC框架
钻研Spring 源码也有一段时间了,对Spring IoC的实现原理理解算是比较透彻了,要实现一款IoC容器,简单的概括无非需要以下几个步骤: 1.定义用来描述bean的配置的Java类,例如我们有 ...
随机推荐
- PS/2接口
ps/2接口标准的发展过程 随着计算机工业的发展,作为计算机最常用输入设备的键盘也日新月异.1981年IBM推出了IBM pc/XT键盘及其接口标准.该标准定义了83键,采用5脚DIN连接器和简单的串 ...
- 查找最小的K个元素,使用最大堆。
查找最小的K个元素,使用最大堆,具体代码如下: #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace st ...
- HiveServer连接优化
引言 数据平台目前通过Hive SQL的方式提供数据分析服务,系统使用多台HiveServer(JDBCServer)接收客户端连接请求,实际使用场景中频频出现HiveServer内存消耗过多导致 ...
- win7配置iis 出现:HTTP 错误 403.14 - Forbidden
打开 IIS 管理器. 在“功能”视图中,双击“目录浏览”. 在“目录浏览”页上,在“操作”窗格中单击“启用”. 确认站点或应用程序配置文件中的 configuration/system.webSer ...
- 浅谈SQL Server中的快照
原文地址:http://www.cnblogs.com/CareySon/archive/2012/03/30/2424880.html 简介 数据库快照,正如其名称所示那样,是数据库在某一时间点的视 ...
- linux之sed用法【转载】
sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为: sed ...
- 【2013杭州区域赛】部分题解 hdu4770—4780
1008: 题意: 有20W个数,每个数都在20W以内,现在有20W个询问,每次询问L,R区间内不会打架的数有多少个 定义两个数不互质 就会打架 解法: 脑洞很大的一道题,先要进行预处理,对每一个数预 ...
- 关于Android API的理解
举个例子: 比如程序中用到了android.content.ClipboardManager这个类, 而该类是在API 11才添加到 “库”. (原谅我,不理解Google API 文档里的 adde ...
- ObjectContext
ObjectContext 类 提供用于查询和使用对象形式的实体数据的功能.它封装了与数据库的底层连接,使你能执行对象查询. ObjectContext封装 .NET Framework 和数据库之间 ...
- ubuntu进入命令登录界面
按ctrl+alt+F1或者ctrl+alt+F2进入系统终端,可以以命令行界面登录系统.