自己动手写框架——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类,例如我们有 ...
随机推荐
- poj Monthly Expense
http://poj.org/problem?id=3273 #include<cstdio> #include<cstring> #include<cmath> ...
- android 自定义titlebar
首先,修改标题栏的宽度和背景,在style.xml中添加: <style> <item name="android:background">@drawabl ...
- POJ3083 Children of the Candy Corn(搜索)
题目链接. 题意: 先沿着左边的墙从 S 一直走,求到达 E 的步数. 再沿着右边的墙从 S 一直走,求到达 E 的步数. 最后求最短路. 分析: 最短路好办,关键是沿着墙走不太好想. 但只要弄懂如何 ...
- HDOJ(HDU) 1862 EXCEL排序(类对象的快排)
Problem Description Excel可以对一组纪录按任意指定列排序.现请你编写程序实现类似功能. Input 测试输入包含若干测试用例.每个测试用例的第1行包含两个整数 N (<= ...
- Android Memory Leak
线程也是造成内存泄露的一个重要的源头.线程产生内存泄露的主要原因在于线程生命周期的不可控.1.看一下下面是否存在问题 public class ThreadActivity extends Activ ...
- 尚学堂 JAVA Day1 概念总结
1.什么是计算机语言?一些符号,这些符号按照计算机硬件结构可以理解的方式排列组合,方便人与计算机,计算机与计算机之间进行信息的交换. 2.什么是机器语言?就是简单的二进制0和1的组合.该语言是计算机硬 ...
- HTTP学习笔记2-请求结构
8,HTTP请求 客户端通过发送HTTP请求向服务器请求对资源的访问. HTTP请求由三部分组成,分别是:请求行,消息报头,请求正文. 9,HTTP请求-请求行 请求行以一个方法符号开头,后面跟着请求 ...
- SVN和Maven及Jenkins(转)
目前项目组在开发一个项目,由多个子模块构成,构建工具是maven,版本控制工具是svn.本文想对如何结合使用maven和svn提出一点初步的想法 一.只有svn的情况 首先考虑没有maven的情况.这 ...
- PHP常用封装类
1.mysql.class.php <?php // namespace Package; /** * MySQL 类 * @author cxm <tsai.er6@gmail.com& ...
- server的散热和Linux中温度的检測
当server被放在散热条件不好的条件下,这样会导致硬盘驱动过早损坏,而且server其它的组件也会非常快出现问题. 现代的server主板检測到CPU过热的时候,一般会限制CPU的频率,所以即使se ...