我的一篇《
一个简单的基于约定优于配置(Coc)的对象工厂实现
》(http://leospace.iteye.com/blog/973744)已经对单纯使用Coc的方式实现DI进行了讨论,并且实现了一个最简的实现,目的是排除其他约束干扰以便于验证可行性。但是这个实现并不能应用于实际的开发,因为它并不能更加适应于实际的情况。实际的情况是有很多接口依赖(比如一个属性的类型就是一个接口),这时这个实现根本无法确认使用这个接口实现的哪一个!另外也没有办法知道一个值类型的属性具体的值,只能给赋予0,而且都是基于属性注入的方式,不符合实际要求,也不太灵活。
所以逐步增加针对实际应用的支持是必要的.下图是按上篇中实现的简单工厂作为基础的,并实现了Coc和XML以及AOP的核心功能的库,这个库以后将做为一整套方案的基础核心,这个库暂时叫做Sim Object Builder
流程:
1) 当实例化SimApplicationContext时,传入一个预先配置好的XML配置文件(其中声明了对象的依赖关系),此时
当GetObject时,框架是按Coc(约定优于配置)+XML配置的方式进行的,首先构造按Coc解析出来而产生的ObjectDefinition, 然后在检查XML,如果发现有接口DI或者值的声明,那么框架自己自动合并XML产生的ObjectDefinition和Coc方式产生的ObjectDefinition.
如果实例化SimApplicationContext时,没有传入XML配置文件,那么直接使用Coc的方式产生ObjectDefiinition
2)框架在得到ObjectDefinition后,自动将其注册在ObjectDeifnitionStore中,以备以后重用(因为使用反射解析是需要花费不少时间的,所以缓存起来)。
3)框架开始调用DynaObjectTypeFactory的CreateType方法,根据ObjectDefinition的指示生成代理类型(使用Emit生成),但是它会根据是否需要生成代理类型而生成,含义是:一旦ObjectDefinition是指明至少一个方法有Advice(一个方面,AOP的一个方面实现,此框架用IAdvice表示),或者至少一个属性启动了延迟加载的功能,那么DynaObjectTypeFactory会采用生成代理类型的方式返回新的类型,否则直接返回一个目标类型(真实类型,不是代理的)。
4)然后框架开始调用BasicCocObjectFactory的GetObject方法,通过方法参数传入刚刚DynaObjectTypeFactory返回的Type,然后Coc使用反射递归地把各个对象包含依赖的对象全部实例化并组装在一起。
5)最后,将创建的“主”对象放到ObjectPoolService中(以便重用),并返回给客户端程序使用。
这里BasicCocObjectFactory就是前面一篇文章中描述和实现的那个简单Coc工厂,这个框架以此为基础进行拓展而形成的,BasicCocObjectFactory使用BasicObjectFactory实例化每一个依赖的对象和主对象。BasicObjectFactory是一个最最简单的对象工厂,也就是用反射工具把传进来的类型实例化了而已,不负责实例化依赖的对象。
另外,Type进行的缓存(并提供文件系统监视器,会自动刷新),使得解析过程的花费减到相对较低,下次调用GetObject时,实际上是使用缓存了ObjectDefinition和缓存了的Object实例。除非环境有变化,才会刷新缓存。
ApplicationContext采用了树型结构的管理,用以简化依赖配置的管理:子容器可以重用父容器的配置(子容器的XML配置文件越来越简单),GetObject方法能够在这个树里找到目标的Object.
值得注意的是,这个框架提供了很好的解耦,对于ObjectDefinition它并不关心依赖配置信息存在何处,是什么保存的(比如xml,txt,ini等等),它都能合并成ObjectDefinition,并且可以提供自己的资源访问器(自定义开发),并且对于DynaObjectTypeFactory而言只接受ObjectDefinition,那么就有效地隔离了资源的差一性,使用Meshup的办法来组合
ObjectDefinition,然后ObjectFactory只是简单实例化组装而已,并能提供基于代理的AOP和延迟加载能力。整个结构简单,概念一致。
这个代码已经完成了将近60%,我会在以后提供出来,协议为LGPL.同时提供Mono、.Net、Java的版本。