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

转载 2006年06月10日 16:16:00

本系列的全部源代码及二进制文件可以从这里下载:IocInCSharp.rar

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

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

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

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

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


本部分示例代码请参考"src/Step3-Reflection"目录

三、基于配置文件和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");
         else
            Console.WriteLine("Got an Error!");
      }
   }
}

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

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

aven2+spring(ioc aop)+struts+mybatis

  • 2017年03月18日 13:33
  • 28KB
  • 下载

ioc AOP深入了解

  • 2014年11月25日 16:48
  • 842KB
  • 下载

SpringMVC学习笔记(一)——初步了解IOC,AOP,MVC和ORM

一直以来只专注于工作内容,由于工作经历的关系,一向对于框架不甚重视,认为框架反而束缚了自己的编码,近期由于被大连的某世界500强公司(既然是技术博文,这里不想无意义的黑,所以隐去名字)坑了一把,商定好...

带你逐步深入了解SSH框架——spring的ioc操作(注解)和aop概念

. 今天内容介绍 1 spring的bean管理(注解) (1)使用注解创建对象 - 四个注解 (2)使用注解注入属性 - Autowired - Resource (3)xml和注解方式混合...

spring IOC AOP simulation.rar

  • 2017年11月28日 17:52
  • 374KB
  • 下载

spring、ioc、aop、callback

  • 2012年10月23日 21:59
  • 5.18MB
  • 下载

关于spring框架中的IOC/DI和AOP,以及声明式事务管理的理解

IOC/DI:中文意思控制反转/依赖注入,针对以前编程,类中的属性都是写死的,直接在程序中给成员变量初始化。这样的编程,耦合度太高,代码的灵活性和扩展性太差。spring的处理方式是,在配置文件中,将...

IOC(DI)与AOP概念的理解

  • 2017年05月25日 08:55
  • 33KB
  • 下载

spring Aop/Ioc

  • 2008年07月19日 11:48
  • 24KB
  • 下载

Spring中IOC与AOP心得

我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入,和AOP,面向切面编程,这两个是Spring的灵魂。 主要用到的设计模式有工厂模式和代理模式。 IOC就是典型的工厂...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:你真的了解Ioc与AOP吗?(2)
举报原因:
原因补充:

(最多只允许输入30个字)