开源Castle框架浅析

Castle是由Hamilton Verissimo撰写的,从2003年就开始开发,并在2006年11月发布了1.0 RC2 。2007年09发布了1.0 RC3版本。Castle是个轻量级(Lightweight)容器(Container)、实现 IoC(Inversion of Control)概念,是一个全方位的应用程序(Application)框架(Framework),并提供相关的一系列工具。

Castle的核心是个轻量级(Lightweight)容器(Container),实现了IoC(Inversion of Control)模式的容器,基于此核心容器所建立的应用程序,可以达到程序组件的松散耦合(Loose coupling),让程序组件可以进行测试(Testability),这些特性都使得整个应用程序可以在架构上与维护上都能得到相当程度的简化。

轻量级(Lightweight)

Castle的核心的程序集只有不到 1MB 的大小,而使用 Castle核心所需要的资源也是很小的,而 Castle是个非侵入性(Nonintrusive)框架,它的目的之一,是让应用程序不感受到框架的存在,减低应用程序从框架移植时的负担。

容器(Container)

Castle核心本身是个容器,管理对象的生命周期、对象的组态、相依注入等,并可以控制对象在创建时是以原型(Prototype)或 单例(Singleton) 的方式来建立。

IoC(Inversion of Control)

Castle的核心概念是IoC,IoC的核心思想是通过消除直接的代码编写并配置需要依赖的服务,来促进松散耦合设计。IoC更具体而易懂的名词是依赖注入(Dependency Injection),使用Castle,您不必自己在程序代码中维护对象的依赖关系,只需在组态档中加以设定,Castle核心容器会自动根据组件将依赖注入指定的对象。除了这些特性之外,Castle的目标是实现一个全方位的整合框架,在 Castle框架下实现多个子框架的组合,这些子框架之间彼此可以独立,也可以使用其它的框架方案加以替代,Castle希望提供 one-stop shop 的框架整合方案。

持久层

Castle提供对持久层的整合,如ADO.NET、O/R Mapping工具(NHibernate、iBATIS.NET)、ActiveRecord、事务处理等。

Web 框架

Castle也提供 Web 框架的解决方案,Castle MonoRail — 一个构建于ASP.NET(不要和ASP.NET中的WebForms混淆)之上的Web框架。它以控制器作为Web应用程序中的主要角色,决定流程,委托到其他层并选取视图来呈现,因此它只关心应用程序的流程逻辑。视图,另一方面也只关注表现逻辑。这是和标准的WebForms模式最大的不同之处。但您也可以将自己所熟悉的Web框架与Castle整合,像WebForm等,都可以与Castle整合而成为适用于自己的解决方案。 
对于一些服务,例如Remoting、Mail、WCF、缓存、任务调度等,Castle不直接提供实现,而是采取抽象层方式进行包装,让这些服务在使用时可以有一致的使用模式且更为方便。

以前对Castle比较陌生,它是一个开源的框架,对于程序员来说,面对java那么多的框架,能够开发.NET的Castle也是不错的事情。网上很多很多文章都在讲在asp.net项目中应用访问Castle IoC容器的方法。Castle的核心概念是IoC, IoC的抽象概念是”依赖倒置”,像是“高层模块不应该依赖低层模块,而是模块都必须依赖于抽象”是IoC的一种表现,“实现必须依赖抽象,而不是抽象依赖实现”也是IoC的一种表现,“应用程序不应依赖于容器,而是容器服务于应用程序”也是IoC的一种表现。 IoC全名Inversion of Control,英文翻译过来的话,就是“控制反转”。初看IoC,从字面上不容易了解其意义,我觉得要了解IoC,要先从Dependency Inversion开始了解,也就是依赖关系的反转。 

简单的说,在模块设计时,高层的抽象模块通常是与业务相关的模块,它应该具有重用性,而不依赖于低层的具体模块,例如如果低层模块原先是软盘存取模式,而高层模块是个存盘备份的需求,如果高层模块直接调用低层模块的函数,则就对低层模块产生了依赖关系。

在设计上希望模块都依赖于模块的抽象,这样才可以重用高层的业务设计。 如果以面向对象的方式来设计,依赖倒置(Dependency Inversion)的解释变为程序不应依赖实现,而是依赖于抽象,实现必须依赖于抽象。来看看下面这个 .NET 程序:

public class BusinessObject {

    private FloppyWriter writer = new FloppyWriter();

    ....

    public void Save() {

        ...

        writer.SaveToFloppy();

    }

}

在这个程序中,BusinessObject 的存盘依赖于实际的 FloppyWriter,如果今天想要将存盘改为存至 Usb 硬盘,则必须修改或继承 BusinessObject 进行扩展,而无法直接使用BusinessObject。 如果透过接口的声明,可以改进此一情况,例如:

public interface IDeviceWriter {

    public void SaveToDevice();

}

public class BusinessObject {

    private IDeviceWriter writer;

    public DeviceWriter

    {

      Set

      {

          this.writer = value;

      }

    }

    public void Save() {

        ....

        writer.SaveToDevice();

    }

}

这样一来,BusinessObject 就是可重用的,如果今天有存储至Floppy或Usb硬盘的需求,只要实现IDeviceWriter即可,而不用修改BusinessObject:

public class FloppyWriter :IDeviceWriter {

    public void SaveToDevice() {

        ....

        // 实现储存至Floppy的程序代码

    }

}

public class UsbDiskWriter : IDeviceWriter {

    public void SaveToDevice() {

        ....

        // 实现储存至UsbDisk的程序代码

    }

}

从这个角度来看,Dependency Inversion的意思就是程序不依赖于具体实现,而是程序与实现都要依赖于抽象。IoC的Control是控制的意思,其实其背后的意义也是一种依赖关系的转移,如果A依赖于B,其意义即是B拥有控制权,您想要转移这种关系,所以依赖关系的反转即是控制关系的反转,藉由控制关系的转移,可以获得组件的可重用性,在上面的 .NET 程序中,整个控制权从实际的FloppyWriter转移到抽象的IDeviceWriter接口上,使得BusinessObject、FloppyWriter、UsbDiskWriter这几个实现依赖于抽象的IDeviceWriter接口。程序的业务逻辑部份应该是可以重用的,不应受到所使用框架或容器的影响,因为可能转移整个业务逻辑至其它的框架或容器,如果业务逻辑过于依赖容器,则转移至其它的框架或容器时,就会发生困难。

IoC 在容器的角度,就是“不要向容器要求您所需要的(对象)资源,容器会自动将这些对象给您!”。IoC 要求的是容器不侵入应用程序本身,应用程序本身提供好接口,容器可以透过这些接口将所需的资源注入到程序中,应用程序不向容器主动要求资源,故而不会依赖于容器的组件,应用程序本身不会意识到正被容器使用,可以随时从容器中脱离转移而不用作任何的修改,而这个特性正是一些业务逻辑中间件最需要的。

posted on 2012-11-19 12:06  一个石头  阅读(2113)  评论(0)    收藏  举报