本文导读:1楼:简介与DEMO下载地址
2楼:使用Elite Container的典型开发步骤说明
3楼:DEMO目录说明
4楼:DEMO简要说明
5楼:其它说明

解决方案 »

  1.   

    一、简介:  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
      

  2.   

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

  3.   

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

  4.   

    四、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作为基类的类。
      

  5.   

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

  6.   

    to #8:思想就肯定不是原创了,IoC思想在其它语言中已经被应用很久了,Java和C#也已有很多IoC容器框架。至于具体到这个容器的编写上,除了配置方式参考了Spring外(因为个人觉得Spring的配置方式已经很灵活了),其它代码完全原创。
      

  7.   

    ioc、企业级。lz可否介绍一下应用场合?以及其它做法为什么不能胜任?
      

  8.   

    to 10#:其它做法也是可以胜任的,这并不是唯一的解决方案,但会是一个比较好的方案。籍由把对象的依赖关系配置化,可以更有效的降低对象间的耦合,实现组件的重用和增量式开发。例如说,我在开发项目A的时候,我可以先定好其业务的接口IBiz,然后实现这个接口ImplBizA;下次再做项目B的时候,我发现B跟A的业务是很像的,只是业务逻辑有一些区别,那么我只需要重写一个IBiz的实例ImplBizB,然后在配置中替换掉ImplBizA就完事了,可能连程序都不用重新编译。
      

  9.   

    这个东西说白了就是管理层与层之间的对象关系,使对象关系更松散!
    harryfin老大,aop做了没
      

  10.   


    如果这样,开发的效率应该会提高很多啊
    为什么java开发给人(至少是我)的感觉却是重量级很多,效率也非常低?
    是它们的业务就很复杂?如果用delphi去做,要花更多的时间?平时得到印象一般都是:用delphi花200万能做的项目,用java做,一般都是要500-1000万以上。。(硬件的开销也高至少一倍)
      

  11.   

    to 14#我觉得IoC/DI最主要在解决组件重用和解耦这两个问题上比较出色,开始的时候可能确实要比拖控件多写不少代码,但是随着不断积累,便会越来越快。至于轻量级和重量级,就要看框架需要的资源,还有是否对程序的入侵性大来决定了。Java的低效不知道你是指开发效率低还是指运行效率低。前者的话我没有实际经历过,有朋友也对我这么说过,所以不发表太多意见;后者的话,应该是属于JAVA本身的问题了。在到业务是否复杂这点,就更加和框架、开发工具无关了,但是我觉得越是复杂的业务,就更应投入更多的资源在起始的地方,否则很可能在后面就慢慢地把项目做死了。相信你也见过很多代码看了谁都想骂的DELPHI程序吧,为什么有些公司会对DELPHI落得一种“不可靠,质量差”的印象,很大程度就是出在这。结构不好,修改困难,代码失控,就算改好了,测试也跟不上,品质自然就差了。它山之石,可以攻玉。我觉得Java和C#还是有不少可借鉴的地方的,尤其是在架构、开发模式这些地方(虽然技术细节可能有比不上DELPHI的地方),这是我这年来的体会。欢迎大家热烈讨论。
      

  12.   

    我说的我印象中的java重量级、慢,主要是指开发效率低(同样中小规模的项目,费用高2倍以上),其次才是运行效率低(同样中小规模的项目,硬件投入大一倍以上)
    只是没接触特别大的项目,不敢确认:这么大的复杂度下,delphi是不是根本无法胜任?还是仍然可以完成的很好至于拖控件,那是客户端的具体模块里的事情了
    如果项目功能分解得好,模块间尽量独立,每个模块的开发效率高,也是好事系统架构当然很关键,它从来都是很重要的,但是与具体界面怎么实现,好像不冲突。只要能无限地扩展功能模块,方便是管理好这些模块,就是很好的架构了DELPHI的“不可靠,质量差”印象,感觉是写服务端代码时,容易遇到。个人感觉是string的方便的方面:内存管理容易被疏漏。还有一个是多线程的实现上,基本是不能太依赖控件,还是想vc一样采用api才会能避免问题。
      

  13.   

    只要能无限地扩展功能模块,方便【地】管理好这些模块,就是很好的架构了 DELPHI的“不可靠,质量差”印象,感觉是写服务端代码时,容易遇到。个人感觉是string的方便的【反】面:内存管理容易被疏漏。还有一个是多线程的实现上,基本是不能太依赖控件,还是想vc一样采用api才会能避免问题。
      

  14.   

    DELPHI 7写服务端,如果不用内存管理的,很容易产生内存碎片,后面版本在这方面有改进
    线程TTHREAD类我觉得封装得还可以,
    如果自己用API来写,如果不用和VCL对象交互,我觉得也没什么大问题,和VCL交互 Synchronize 就麻烦点, 用消息其实效率比较低的
      

  15.   

    to 13#看漏了这个回帖了 -_- 有计划,但是D2010以下的版本实现起来,暂时还有点未串通的地方,可能到时还要向大家请教。另外很久前riceball写过个MeAop,是基于内存打洞来实现拦截的(他比较不屑用接口的这种方式,呵呵),最新版本是1.2。不知道现在在实际项目中应用得怎样呢?不过我个人比较喜欢接口的方式,虽然效率会低点,但是可以更好地应用一些设计模式,如代理模式。
      

  16.   

    @Harryfin
    老大,还是被你抢先了一步啊~呵呵,我们目前正在准备Delphi Spring Framework的V0.2版本,IoC容器也初步完成了。过几天我也发布下,好听听大家的意见:)
      

  17.   

    EliteContainerD7没有包含源码?只有bpl?
      

  18.   

    to #30嗯,暂时只提供dcp和dcu,以后会考虑开放源代码,例如说比较完善之后。目前试用的话,引用dcp即可,例子基本已覆盖了主要功能,就差太懒没有补上个xsd,这个是应该提供的,呵呵。如果有疑问的话,我会在这里提供详细的回答。
      

  19.   

    delphi版牛人还是多,爱delphi、顶delphi
      

  20.   

    dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
      

  21.   

    楼上是ET,BS装菜鸟 - -
      

  22.   

    早上我就在想  ZuoBaoquan  看到你這個貼子, 會有什麼想法。 
      

  23.   

    把MeAop的地址放一下,方便大家
    http://code.google.com/p/mesdk/
      

  24.   


    Ser_U ftp服务器 用delphi写的,不是很好吗
      

  25.   


    当然不是:delphi就写不出可靠、高本质的服务端程序
    而是:不非常注意,仍然按客户端的快速方式开发,就很容易导致“不可靠,质量差”
      

  26.   

    对了,大家觉得对于对象节点的名称,是用obj好还是用object好呢?开始是用后者的,后来考虑到手动书写的话,重复量比较大,又改成了前者。如果从可读性来看,那肯定是后者更好,同理的还有property节点和constructor-arg节点。
      

  27.   

      借助Elite Container和Ioc思想,你可以更轻易地构建出具有松散耦合、重用度高的应用程序。它的核心思想就是拆分功能的接口和实现,上层只依赖于下层的接口,然后通过Elite Container的配置,把不同的实现类注入到该接口中,达到更换功能,也就是复用已有代码的目的。设计人员可以真正地发挥好自己的面向对象思想和相关设计模式,来架构企业级的应用程序,而无需象以前那样,在Delphi中用起面向对象总有点捉襟见袖的感觉。//----------------
    这种动态配置对象的功能的确很重要! JAVA程序的部署有时候都需要专业的人员.另外
    DELPHI封装了UI层和数据层. 两层中间的东西怎么写的都有.这也造成了 "DELPHI的“不可靠,质量差”印象,"