你真的了解Ioc与AOP 吗?(2)

三、基于配置文件和Reflection的工厂模式

为了消除MainApp对其它组件的依赖性,我们引入工厂模式,并且根据配置文件指定的装配规程,利用.net提供的反射技术完成对象的组装工作。本部分代码仅仅提供一种功能演示,如果实际应用仍需进一步完善(建议使用一些成型的Ioc框架,例如Spring.net或Castle等)。经过改造后的系统,组件间依赖关系如下图:

可以看出这次实现了真正的“针对接口编程”。所有的组件只依赖于接口。MainApp所需的对象是由工厂根据配置文件动态创建并组装起来的。当系统需求发生变化时,只需要修改一下配置文件就可以了。而且MainApp、SayHello和HelloGenerator之间不存在任何的依赖关系,实现了松耦合。

这是如何实现的呢?我们首先要能够解析配置文件中的信息,然后建立包含相关信息的对象。最后根据这些信息利用反射机制完成对象的创建。首先我们看一下配置文件所包含的内容:

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><sectionGroup name="IocInCSharp"><section name="objects" type="IocInCSharp.ConfigHandler, MainApp" /></sectionGroup></configSections><IocInCSharp><objects><object name="SayHello" assembly="SayHello.dll" typeName="IocInCSharp.SayHello"><property name="HelloGenerator" assembly="HelloGenerator.dll" typeName="IocInCSharp.CnHelloGenerator"></property></object></objects></IocInCSharp>
</configuration>

从中我们可以看出,我们实现了一个IocInCSharp.ConfigHandler类,用来处理配置文件中 IocInCSharp\objects结点中的内容。ConfigHandler类将根据该结点下的内容处理并创建一ConfigInfo对象(关于 ConfigInfo、ObjectInfo以及PropertyInfo的代码可自行查看源代码,这里就不再赘述)。ConfigHandler类的代码实现如下:

using System;
using System.Configuration;
using System.Xml;
namespace IocInCSharp
{public class ConfigHandler:IConfigurationSectionHandler{public object Create(object parent, object configContext, System.Xml.XmlNode section){ObjectInfo info;PropertyInfo propInfo;ConfigInfo cfgInfo = new ConfigInfo();foreach(XmlNode node in section.ChildNodes){info = new ObjectInfo();info.name = node.Attributes["name"].Value;info.assemblyName = node.Attributes["assembly"].Value;info.typeName = node.Attributes["typeName"].Value;foreach(XmlNode prop in node){propInfo = new PropertyInfo();propInfo.propertyName = prop.Attributes["name"].Value;propInfo.assemblyName = prop.Attributes["assembly"].Value;propInfo.typeName = prop.Attributes["typeName"].Value;info.properties.Add(propInfo);}cfgInfo.Objects.Add(info);}return cfgInfo;}}
}

通过ConfigHandler的解析,我们最终得到一个ConfigInfo实例,Factory就是根据这个实例中所包含的配置信息,利用反射技术对所需对象生成并组装的。SayHelloFactory的代码如下:

using System;
using System.IO;
using System.Configuration;
using System.Reflection;
namespace IocInCSharp
{public class SayHelloFactory{public static object Create(string name){Assembly assembly;object o = null;object p;string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;ConfigInfo cfgInfo = (ConfigInfo)ConfigurationSettings.GetConfig("IocInCSharp/objects"); ObjectInfo info = cfgInfo.FindByName(name);if(info != null){assembly = Assembly.LoadFile(rootPath + info.assemblyName);o = assembly.CreateInstance(info.typeName);Type t = o.GetType();for(int i=0; i<info.properties.Count; i++){               PropertyInfo prop = (PropertyInfo)info.properties[i];assembly = Assembly.LoadFile(rootPath + prop.assemblyName);p = assembly.CreateInstance(prop.typeName);t.InvokeMember(prop.propertyName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, o, new Object[] {p});}}return o;}}
}

在上面这段代码中,重点注意三条命令的使用方法:

assembly = Assembly.LoadFile(rootPath + prop.assemblyName);
p = assembly.CreateInstance(prop.typeName);
t.InvokeMember(prop.propertyName, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty, null, o, new Object[] {p});

Assembly.LoadFile()用于将外部文件装载进来;assembly.CreateInstance()根据装载进来的程序集创建一指定类型的对象;t.InvokeMember(prop.propertyName, ........BindingFlags.SetProperty, null, o, new Object[] {p})利用反射机制对创建出来的对象设置属性值。

我们的Factory就是利用这种方式根据配置文件动态加载程序集,动态创建对象并设置属性的。有了这个Factory,MainApp中的内容就很简单了:

using System;
namespace IocInCSharp
{public class MainApp{public static void Main(){ISayHello sayHello = (ISayHello)SayHelloFactory.Create("SayHello");if(sayHello != null)sayHello.SayHelloTo("zhenyulu");elseConsole.WriteLine("Got an Error!");}}
}

现在,MainApp只依赖于接口,不再依赖于其它组件,实现了松耦合。在本例子中,大家可以尝试将配置文件中的IocInCSharp.CnHelloGenerator更改为IocInCSharp.EnHelloGenerator,看看是否输出内容由中文变为了英文。这便是“注入”的效果。

从上面这个例子我们可以看出,通过自定义配置文件和.net中的Reflection技术,我们自己就可以开发Ioc应用,根据配置文件的信息自行组装相应的对象。但是Reflection编程的技术门槛还是比较高的,并且在实际应用中配置文件的格式、Handler的设计都不是象上面代码那样的简单。不过幸好我们现在有很多的Ioc容器可供选择,它们都提供了完整的依赖注入方式,并且比自己写代码更加成熟、更加稳定。使用这些框架可以让程序员在三两行代码里完成“注入”工作。在我们下一个案例中,我们将使用Spring.net实现依赖注入。我们会发现仅仅添加几行代码并更改一下配置文件就可轻松实现依赖注入。(待续)

转载于:https://www.cnblogs.com/kevin-wang/archive/2010/04/29/1723459.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263951.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于一道数据库例题的解析。为什么σ age22 (πS_ID,SCORE (SC) ) 选项是错的?

本人大二学子。近段时间在做数据库复习题的时候遇到一道题&#xff0c;如下。 有关系SC&#xff08;S_ID&#xff0c;C_ID&#xff0c;AGE&#xff0c;SCORE&#xff09;&#xff0c;查找年龄大于22岁的学生的学号和分数&#xff0c;正确的关系代数表达式是&#xff08; &#…

java获取表主外键_通过 jdbc 分析数据库中的表结构和主键外键

文章转自&#xff1a;http://ivan4126.blog.163.com/blog/static/20949109220137753214811/在某项目中用到了 hibernate &#xff0c;大家都知道 hibernate 是 ORM 框架&#xff0c;他是有能力根据实体生成数据库表的。我们在单元测试的时候用到了 dbUnit &#xff0c;dbUnit 可…

c#扩展方法奇思妙用高级篇四:对扩展进行分组管理

从系列文章开篇到现在&#xff0c;已经实现的很多扩展了&#xff0c;但过多的扩展会给我们带来很多麻烦&#xff0c;试看下图&#xff1a; 面对这么多“泛滥”的扩展&#xff0c;很多人都会感到很别扭&#xff0c;的确有种“喧宾夺主”的感觉&#xff0c;想从中找出真正想用的方…

Robot Framework-Ride界面介绍及库的添加

Ride界面介绍1. Ride简介1.1什么是RideRide是robotframework的UI界面, 以HTML格式提供易于阅读的结果报告和日志, 用户可以自定义基于Python的测试库, 提供支持selenium的Web测试,语法和python很像。1.2 Ride界面介绍1.2.1主界面介绍&#xff1a; 1.2.2运行按钮和工程目录&a…

Android项目实战(三):实现第一次进入软件的引导页

最近做的APP接近尾声了&#xff0c;就是些优化工作了&#xff0c; 我们都知道现在的APP都会有引导页&#xff0c;就是安装之后第一次打开才显示的引导页面&#xff08;介绍这个软件的几张可以切换的图&#xff09; 自己做了一下&#xff0c;结合之前学过的 慕课网_ViewPager切换…

LESS CSS 框架简介(转)

为什么80%的码农都做不了架构师&#xff1f;>>> 原文地址:http://www.ibm.com/developerworks/cn/web/1207_zhaoch_lesscss/ 简介 CSS&#xff08;层叠样式表&#xff09;是一门历史悠久的标记性语言&#xff0c;同 HTML 一道&#xff0c;被广泛应用于万维网&#…

IP通信基础 实验三

PC端配置&#xff1a;配置ip地址 配置网关 交换机(左)配置&#xff1a;①创建VLAN system-view vlan 10 vlan 20 ②配置PC端接口 interface gi 1/0/1 port link-type access port access vlan 10 interface gi 1/0/2 port link-type access port access vlan 10 interface gi 1…

图像处理(三)

VC实现对不同信号波形相似程度的判别摘要&#xff1a;本文介绍了利用相关对信号波形进行相似程度的判别方法。通过该技术可以对采集到的多种类型的数据信号间的相似度进行判别。本算法由Microsoft Visual C 6.0实现。 一、 引言 在工程上我们经常要判断某设备产生的实际波形信号…

Servlet3.0学习总结(四)——使用注解标注监听器(Listener)

Servlet3.0提供WebListener注解将一个实现了特定监听器接口的类定义为监听器&#xff0c;这样我们在web应用中使用监听器时&#xff0c;也不再需要在web.xml文件中配置监听器的相关描述信息了。 下面我们来创建一个监听器&#xff0c;体验一下使用WebListener注解标注监听器&am…

PHP ThinkPHP学习第一步(搭建及认识ThinkPHP入口文件)

ThinkPHP包下载网址&#xff1a;http://www.thinkphp.cn本人下载3.2版本中的完整版&#xff0c;解压如下取其中的ThinkPHP文件于开发网站的根目录&#xff0c;并建立入口文件index.php入口文件index.php详细内容如下&#xff1a;<?php/** 本文件为thinkPHP的入口文件&#…

iptables 基础

SNAT 和 DNAT 是 iptables 中使用 NAT 规则相关的的两个重要概念。如上图所示&#xff0c;如果内网主机访问外网而经过路由时&#xff0c;源 IP 会发生改变&#xff0c;这种变更行为就是 SNAT&#xff1b;反之&#xff0c;当外网的数据经过路由发往内网主机时&#xff0c;数据包…

Oracle11g远程连接配置 visual studio 2003

服务器端 配置&#xff1a;oracle11g R2 x64 1.设置监听 a.启动栏 -> 开始 -> 程序 -> Oracle-OraDb11g_home1 -> 配置和移植工具 -> Net Manager b.Oracle Net 配置 -> 本地 -> 监听程序 -> LISTENER &#xff0c;查看是否有本地地址在监听&#xff…

JAVA思维导图学习笔记_8张思维导图,55天学习笔记,帮你入门JavaSE

学完了Java中的基础语法&#xff0c;也就是JavaSE。对其做了一个详细的梳理&#xff0c;也便于以后回顾。其中有些知识点被自己遗漏了&#xff0c;比如正则表达式这些&#xff0c;只能以后找机会补上了。01前言对于计算机基础知识的了解、以及Java相关的软件安装。相关笔记02基…

使用MemoryStream和FileStream

使用MemoryStream和FileStream编程访问文件是通过文件流对象进行的&#xff0c;当应用程序需要访问文件时&#xff0c;必须先创建一个文件流对象&#xff0c;此流对象和文件是一一对应关系。在.NET中&#xff0c;使用抽象基类System.IO.Stream代表流&#xff0c;它提供Read和Wr…

WordPress后台的文章、分类,媒体,页面,评论,链接等所有信息中显示ID并将ID设置为第一列...

WordPress后台默认是不显示文章、分类等信息ID的&#xff0c;查看起来非常不方便,不知道Wp团队出于什么原因默认不显示这个但可以使用Simply Show IDs插件来实现 不使用插件,其他网友的实现&#xff1a; <?php /** *为WordPress后台的文章、分类等显示ID From wpdaxue.com …

进程调试--进程启动VS自动附加

程序启动VS自动附加到进程调试 1、 打开注册表regedit 2、 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\currentversion\image file execution options 3、 新建QQ.exe【需要调试的进程名】 4、 右键修改字符串值 5、 F2修改新生成的默认值----debugger 6、右键debugger…

#20175201 实验五 网络编程与安全

一、实验五 网络编程与安全-1 1.实验要求&#xff1a; 两人一组结对编程&#xff1a; &#xff08;1&#xff09;参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA &#xff1b; &#xff08;2&#xff09;结对实现中缀表达式转后缀表达式的功能 MyBC.java&#xff1b…

Scala学习思维导图

转载于:https://blog.51cto.com/thunderkeg/1605365

使用git上传代码到github远程仓库

一、新建代码库注册好github登录后&#xff0c;首先先在网页上新建代码库。 点击右上角“&#xff0b;”→New repository 进入如下页面&#xff1a;按照要求填写完成后&#xff0c;点击按钮创建代码库创建成功。 接下来我们查看一下刚刚创建好的代码库&#xff0c;点击右上角的…

java web开发myeclipse_【java项目实战】一步步教你使用MyEclipse搭建java Web项目开发环境(一)...

首先&#xff0c;在开始搭建MyEclipse的开发环境之前&#xff0c;还有三步工具的安装需要完成&#xff0c;只要在安装配置成功之后才可以进入下面的java Web项目开发环境的搭建。1、安装工具第一步&#xff0c;下载并安装JDK&#xff0c;到官网上下载安装即可&#xff0c;之后需…