你真的了解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,一经查实,立即删除!

相关文章

DataTime转Varchar

SELECT Convert(varchar(100),A.CreateTime,20) FROM [TB_Business_Award] A 转载于:https://www.cnblogs.com/Anthony518/p/10908263.html

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

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

砂.随笔.二十五.如果你是氧气

在跌倒的地方 勇敢站起来 我在这里 在纯真的梦里转载于:https://www.cnblogs.com/aque1984/archive/2010/05/07/1729361.html

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

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

OO第三单元总结:JML

目录 第三单元——jml、junit与图第三单元——jml、junit与图 〇、问题描述 ​ 本单元主题为JML的学习&#xff0c;问题载体为一个无向图路径管理系统。在三次作业种&#xff0c;情景不变&#xff0c;需求递增。因此需要在层次上做好安排。 一、JML语言 理论基础(Level 0) 注释…

沼跃鱼早已看穿了一切 C/C++

沼跃鱼早已看穿了一切 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 593 Solved: 229[Submit][Status][Web Board]Description 沼跃鱼打开密码门后发现门后是一个像迷宫一样的房间&#xff0c;墙上的指示牌写着&#xff1a;房间内某处有一宝箱&#xff0c;但是宝箱被上锁了…

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

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

js 获取java_js中获取当前时间

var d new Date();var date d.getFullYear() "年" (d.getMonth() 1) "月" d.getDate() "日";var myDate new Date();myDate.getYear(); //获取当前年份(2位)myDate.getFullYear(); //获取完整的年份(4位,1970-????)myDate…

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…

preloadlazy load

最近需要用到预加载和延迟加载的东东&#xff0c;就参考写了一个。 支持跨页面&#xff0c;支持超时设置与依赖设置。 (function($) { (function($) {$.preload function(data, cfg) {return new Loader(data, cfg);};var maps {}, on $.event.add, un $.event.remove, hea…

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

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

java gettime_Java Util.getTime方法代码示例

import org.jrobin.core.Util; //导入方法依赖的package包/类private void initGraphPeriodAndSize(Range range, int width, int height, RrdGraphDef graphDef) {// ending timestamp is the (current) timestamp in seconds// starting timestamp will be adjusted for each…

LESS CSS 框架简介(转)

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

全选 删除 分页

前台&#xff1a; <% Page Language"C#"AutoEventWireup"true"CodeFile"benrenbao.aspx.cs"Inherits"benrenbao"%><% Register Assembly"AspNetPager"Namespace"Wuqi.Webdiyer"TagPrefix"webdiyer&…

计算机java考试_2017年计算机java考试试题

正确的道路是这样&#xff1a;吸取你的前辈所做的一切&#xff0c;然后再往前走。以下是小编为大家搜索整理的2017年计算机java考试试题&#xff0c;希望能给大家带来帮助!更多精彩内容请及时关注我们应届毕业生考试网!1). 程序流程图中的菱形框表示的是( )。A.处理步骤B.逻辑处…

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…

java反射 获取方法_java反射之获取类的信息方法(推荐)

本文接上文“老生常谈反射之class类的使用(必看篇)”&#xff0c;以编写一个用来获取类的信息(成员函数、成员变量、构造函数)的工具类来讲解"反射之获取类的信息"1、获取成员函数信息/*** 获取成员函数信息* param obj*/public static void printclassmethodmessage…

Leetcode 刷题笔记

1Two SumEasy2Add Two NumbersMedium3Longest Substring Without Repeating CharactersMedium5Longest Palindromic SubstringMedium141Linked List CycleEasy转载于:https://www.cnblogs.com/Poceer/p/10922646.html