Elite Container DELPHI下的一个轻量级IoC对象容器

一、简介:

  Elite Container是DELPHI下的一个轻量级IoC对象容器(IoC:Inverse of Control,反转控制)。它是参考了Java中的Spring框架(主要是配置文件的写法),并结合DELPHI的特点来构建的。相比Spring的对象容器,它提供的功能更为精简常用(如对象延迟创建、对象属性自动注入等),降低了学习的难度,并且提供了很多扩展点,你只需简单地写一个插件实现类,并在配置文件中进行简单配置,就可以让Elite Container拥有你的自定义功能!

  Elite Container主要拥有以下的一些特性:
  
  1、无论使用或不使用BPL,都可以用Elite Container来构建你的程序(但不建议用纯DLL,因为各DLL中,同一个类的类型信息是不同的,不熟悉相关知识的话,有可能会带来一些问题,而这本身并不是Elite Container的问题)
  2、支持多种属性注入类型,如直接值、枚举、集合、StringList、ObjectList等。其中StringList这种注入方式,在解决键值对配置时非常有用,详细请参看相关例子
  3、支持构造函数注入。但由于Delphi的元信息不够完备,有时需要写一个构造函数调用类(写法很简单),才可让容器正确调用该类和其子类的构造函数,详细请看相关例子另外由于构造函数注入有可能会引起循环注入的问题,因此建议尽量使用属性注入来表达对象的依赖关系,不得已的时候才使用构造函数注入
  4、支持对象配置的继承。省去配置子对象时,又要把父对象的属性配置重新拷贝一遍,既麻烦又难维护。
  5、支持对象属性的自动注入。如果你的属性命名满足一定规则,便可以利用自动注入来省去大量的配置书写
  6、支持配置文件的引入,提高配置文件的可重用性
  7、支持多种对象的生命周期配置(对于无状态的管理类,如逻辑层,单例生命周期是最常用的)
  8、支持对象的别名配置
  9、增强的对象注册机制,可注册非TPersistent为基类的类(常见的如TInterfacedObject),并且容器可以区分不同单元的同名类
  10、兼容使用Delphi的RegisterClass来注册类的遗留模块
  11、大量的自定义插件扩展点。你可以自定义自己的属性注入配置方式、构造函数注入配置方式、对象配置引入方式、对象生命周期管理方式、对象属性自动注入方式等
  12、支持对象的延迟创建。以免容器初始化时,会自动实例化一些需要花费大量时间来创建,而又很少用的类。
  13、大量的可编程接口。你甚至可以自己写一个用INI、或数据库来进行配置的IoC容器!

  借助Elite Container和Ioc思想,你可以更轻易地构建出具有松散耦合、重用度高的应用程序。它的核心思想就是拆分功能的接口和实现,上层只依赖于下层的接口,然后通过Elite Container的配置,把不同的实现类注入到该接口中,达到更换功能,也就是复用已有代码的目的。设计人员可以真正地发挥好自己的面向对象思想和相关设计模式,来架构企业级的应用程序,而无需象以前那样,在Delphi中用起面向对象总有点捉襟见袖的感觉。

  DEMO下载地址:http://download.csdn.net/source/1891434

二、使用Elite Container的典型开发步骤:

  1、新建项目,在项目选项中选择“build with runtime packages”,去掉所有的默认包,然后选择EliteContainerD7
  2、建立应用程序的领域(如对象实体、逻辑处理、接口服务等)
  3、用XML文件来配置这些对象
  4、引用elXMLConfigurateContainer单元,声明一个IelObjectContainer类型的接口变量
  5、给这个接口创建一个TelXMLConfigurateContainer的实例,把这个XML文件的路径(相对或绝对路径均可,构造函数有参数指定),作为参数传入到构造函数中
  6、TelXMLConfigurateContainer创建的时候,会自动初始化生命周期配置为"singleton",并且不是延迟创建的对象
  7、现在可以根据配置文件所配置的对象ID或别名,从容器中获取已配置好的对象或接口了
  8、调用所获取的对象或接口,来完成程序的功能

三、DEMO目录说明:

  Bin 各个例子的可执行程序
  BinConfig 各个例子所用到的配置文件
  Lib 各个例子用到的dcp文件,需要在项目设置的"Build with runtime packages"中引入
  Source 各个例子的源代码。共26个例子,用于详细介绍Elite Container的特性。请务必结合源代码、配置文件和可执行文件来理解,这样才能达到演示的目的。如果要编译例子源代码的话,请把Lib目录添加到Delphi的Library Path下,并修改下项目的输出路径。

四、DEMO简要说明:

  例1:示范了容器最基本的功能。如何获取一个配置好的对象,包括以对象形式获取(GetObj),和以接口的形式获取(GetIntf)。

  例2:示范了容器最基本的功能。与例1不同的是,这个例子中,类被封装了在BPL当中。这种方式是项目实际开发时,最常用的方式(以便重用业务逻辑)。注意在配置对象的时候,对象的class配置,还要加上类所在的bpl文件,然后还要在程序中对类进行注册。

  例3:示范了如何把直接值(字符串、整数等)注入到属性中。这种方式常用于利用配置来改变对象的某些初始状态,例如可以把数据库链接串以这种方式注入到对象中,以便不用重新编译也能改变程序的数据库链接。

  例4:示范了如何把枚举或集合注入到属性中。强大的是,配置中,你既可以写枚举的字符串名称,也可以写枚举的整数值。

  例5:示范了如何把其它配置的对象注入到属性中。属性可以是对象类型,也可以是接口类型(假如被注入的对象,实现了该接口)。这是最常用的注入方式,例如把数据访问对象注入到业务逻辑对象中,以便让业务逻辑对象访问数据库。

  例6:示范了如何配置一个StringList对象,并把它注入到属性中。从配置文件中可以看到,配置的方式非常多。其中KeyValueList和ObjectRefList这两个属性的配置都采用类键值对的形式,这种形式在解决映射关系时,是很常用的。

  例7:示范了如何配置一个ObjectList对象,并把它注入到属性中。注意,ObjectList的OwnsObject参数是默认被设置为false的,也就是说,释放这个ObjectList,不会释放里面的对象。因为Elite Container的单例声明周期是最常用的,因此对象的生命周期应由容器来管理,不应该在ObjectList释放的时候就释放。不过也可以直接把ObjectList配置成管理生命周期,例如它里面的对象的生命周期被配置了为"prototype"的时候。你需要清楚地知道对象的生命周期是如何被管理的,才可正确使用好这种注入方式。

  例8:示范了如何配置一个InterfaceList对象,并把它注入到属性中。

  例9:示范了对象属性自动注入的功能。可以设置为根据属性名称("T"加上属性名来作为对象ID)、属性类型或自动模式,来尝试从容器中获取对象。自动注入会作用于没有手动配置,不是只读,类型是对象或接口的那些属性上。自动注入默认是关闭的(值为"false"),而按属性名称,是最常用的自动注入模式。

  例10:示范了继承父对象的属性配置。才能够配置文件可以看到,TMyObjectB的Count、Text、Day这三个属性的值,均继承了TMyObjectA中的设置。强大的是,你还能进行属性配置的覆盖,可以看到TMyObjectB中Day的值是wdTuesday,而不是TMyObjectA中配置的wdMonday。

  例11:示范了构造函数注入。注意要配置构造函数参数的类型,常见的取值有string、integer、float、boolean、string、enum、set、object、interface等。

  例12:示范了对象配置的引入。通常我们可以给各个组件写独立的配置文件,然后主程序引入这几个组件的配置文件即可。这样便重用了组件的配置文件了。注意,如果对象的配置量非常巨大,可以通过设置lazy="true"来延迟载入该配置文件。

  例13:示范了对象的生命周期配置。默认的三种生命周期是:单例"singleton",该对象的实例由容器来管理(不要自己释放掉它),并且每次获取都是得到同一个实例,这种生命周期是默认的生命周期;原型"prototype",容器只负责对象的创建,而不负责实例的释放,你需要自己来管理它的生命周期;线程单例"per-thread",本质也是单例模式,但是每条线程里都会有一个不同的单例。

  例14:示范了对象的别名声明。此功能常用于整合资源,例如几个组件分别声明了数据库链接的对象ID,我可以通过声明别名,把这几个数据库链接的对象ID都指向同一个对象,那么就实现了几个组件用同一个数据库链接了。

  例15:示范了完成注入后,让对象进行初始化处理。通常可以在这里检查对象的属性有被注入,因为写漏配置的现象有时还是难以避免的。

  例16:示范了如何兼容使用RegisterClass来注册类的老模块。其实使用上是完全一样的,没任何特殊之处。

  例17(进阶功能):示范了如何注入DELPHI自带的类。要注意的是,要手动对这些类进行下注册,其它就没什么特殊了。

  例18(进阶功能):示范了如何获取不同单元中的同名类。配置中,class注意要加上类所在的单元名。

  例19(进阶功能):示范了自定义属性注入的处理。你需要分别写一个属性值识别器和属性值注入器,然后把它在配置中进行配置即可。可以看到,例子的配置中,属性出现了自定义的类型"path"。

  例20(进阶功能):示范了自定义构造函数注入的处理。你需要分别写一个构造函数参数值识别器和构造函数参数值注入器,然后把它在配置中进行配置即可。可以看到,例子的配置中,构造函数参数出现了自定义的类型"owner-selector"。

  例21(进阶功能):示范了如何自定义对象配置引入机制。例子中把对象的配置封装在了DLL中,对配置起到了简单的保护作用。因为Delphi被大量使用在客户端程序中,这跟Java是有区别的。因此这可以说是具有Delphi特色的一个很有用的扩展点。

  例22(进阶功能):示范了自定义对象的生命周期管理方式。

  例23(进阶功能):示范了自定义的对象属性自动注入器的编写。

  例24(进阶功能):示范了如何写构造函数调用器。当出现以下两种情况时,你才需要为类写一个构造函数调用器:基类的构造函数不是虚函数,而你在子类中又声明了该构造函数;基类的构造函数虽然是虚函数,但是在子类中,你对它进行了重新声明,或者提供了重载的版本。一般调用器的逻辑,需要检查参数的个数、签名,根据重载的版本,判断参数是否存在,参数类型是否正确等。

  例25(进阶功能):示范了对象属性的延迟获取。例子中获取TExample时,三个属性均是没值的,只有在它们被访问到的时候,才用容器中获取所配置的对象。这样便大大增加了TExample的获取速度(这三个属性所配置的类,为了演示需要,在创建时都人工sleep了一段时间作为延迟)

  例26(进阶功能):示范了如何注册不是TPersistent作为基类的类。

五、其它说明:

  Elite Container可支持Delphi 7以上的任何版本,目前暂只提供D7的版本供试用。另外放出此DEMO,主要的目的是为了能及时收集大家的反馈意见而已,容器本身不可以避免尚会存在一些问题,如内存泄露、缺乏线程保护等,暂时请勿用于实际项目中,否则后果自负。

原文地址:https://www.cnblogs.com/h2zZhou/p/8004090.html