Easy MVC Framework (eMVC) Developers Guide

来源:互联网 发布:ipcam监控软件 编辑:程序博客网 时间:2024/04/28 15:16

 eMVC Framework

摘自官方 Easy MVC Framework (eMVC) Developers Guide Version 1.0

Chenliang’s blog 翻译

Easy MVC Framework (eMVC) Developers Guide

 

本人能力有限,欢迎大家指正批评。

 

1. Introduction

 

1.1 What’s Easy MVC

Easy MVC或者说是eMVC ,是一个轻量级的的MVC框架,它是为Delphi程序员们开发标准Windwos应用程序而设计的。

 

1.2 Why we need eMVC?

Model-View-Controller (MVC)在计算机编程界早已成为了普遍使用和强大的工具,因特网上有大量的MVC框架(免费的或者商业的)可供程序员们使用,但是,很多框架都是庞然大物,很难去理解它,使用它,尤其对于初学者来说,更是不容易理解。最主要的一点就是,大多数MVC框架都是用java,PHP写的,正因为如此,作者写了个eMVC

 

1.3 What’s an eMVC based application looks like?

eMVC实现了Model-View-Controller设计模式,与其它MVC框架做对比,eMVC引进了一个全新的概念mset(mset),mset这个模块,它可以实现一些它所特有的函数,对于程序而言,它仅扮演一个小的角色。一个标准的mset包含了一个Controller,一个Model和一个或是很多个Views,众所周知,Model所指的是构成应用程序的代码部分,View指的是用户所接触的程序所显示的界面。

这个框架提供了唯一的一个入口点 – ControlCenter ,所有的Controllers必须在ControlCenter那里注册,ControCenter把所有注册的Controllers放在一个队列中。

下面的一张图展示了这个框架下应用程序的基本结构:

ControlCenter

如图所示,基于eMVC框架搭建的应用程序有个ControlCenter,这个ControlCenter包含了以队列的Controllers,每一个Controller是在一个mset里的。

 

2. The Benefits

设计模式中,并不是只有Model-View-Controller模式是一个工业标准。

有许多优秀的书籍和资源可以利用,它们可以帮助项目组快速地去学习它。

对于学习一个框架(例:eMVC),都是要付出十分的努力的,但对于那些勤奋的Delphi开发者来说,学习这样的一门MVC设计模式,是能得到很多好处的。

  • 强调模块化的思维模式将应用程序划分为单独的模块。(高内聚)
  • 代码之间更少的牵连。(低耦合)
  • 加强了开发者与设计者之间的单独协调工作。
  • 加强了代码的可管理能力。
  • 加强了代码的可扩展性。(能够为了适应变化而对代码更改)
  • 对于eMVC的开源许可,我们能够完全地进入源代码。

对于更新的版本,我们可以得到更多有用的函数,你可以在将来得到更多的好处。

3. Essentials

在我们学习eMVC之前,我们最好先学习两个简单,经常使用的设计模式Observer(观察者)和Chain of Responsibility(职责链),这两个模式也是著名的的MVC。

 

3.1. Observer patterns

 

   3.1.1 knowledge

 

   考虑一下这样的情况(Figure3.1),每一个窗体(Observer1,2,3)对应含有一个电子数据表,柱形图表,饼型图,这三个图形所描述的是同一个数据实体,但这三个窗体都不知道彼此,当你想使用哪个的时候,你随便使用哪个好了。当你在电子数据表中更改数据的时候,其他两个图(柱形图表,饼型图)会立刻随之更改。其它的,看下图,就发挥你的想象吧,什么是Observer patterns就迎刃而解了。

Observer patterns

Observer pattern 就是怎样在他们三者之间长生一定得牵连关系。

我们可以从图中可知,重点的实体就是Observable subject 和 Observer.

这里我总结了几点规律(关于这个模式)

a)一个Observable Subject有任意数量的独立的Observer。

b)所有的Observers必须注册到Observable Subject。

c)所有的Observers都在监听Observable Subject,当Observable Subject受到改变时,所有的Observers都会被告知。

d)每个Observer都会要求Observable Subject实时地,动态地去更改状态。

 

   3.1.2 Observer pattern in eMVC

 

Observer patterns in eMVC

Figure 3.2 是在eMVC框架里定义的类模型。对于Observer patterns,这里有两个接口 IObservable 和 IObserver。

与之上的图Figure 3.1所对应上去就是IObservable是为了Observable Object设计的,IObserver是为了Observers设计的。

TObservable 默认地实现IObservable接口,它源自TintefacedObject

下面来看一些这两个接口的源码

//Observer interface
IObserver = interface
    ['{3E91264F-BBC0-44DF-8272-BD8EA9B5846C}']
    Procedure UpdateView(o: TObject);
end;
//Observable interface
IObservable = interface
    ['{A7C4D942-011B-4141-97A7-5D36C443355F}']
    procedure RegObserver(observer: IObserver);
    procedure Notify(o: TObject);
end

相当的简单,下面具体地来讲解一下。

A:IObservable

IObservable有两个过程:RegObserver()和Notify()。RegObserver()是用来注册Observers的,当Observable Subject改变的时候,调用Notify()来告诉所有的Observers改变的情况。

B:IObserver

IObserver有一个过程UpdateView(),它将在Notify()被调用的时候自动触发,为什么呢?可以仔细看下在TObservable中Notify()的实现。

C:TObservable

TObservable是IObservable接口的默认实现,我强烈要求:当你新建一个类的时候继承自TObservable,而不是IObservable接口。

在TObservable类中有一块私有的属性iObservers,它掌握着所有的已注册的Observers.

在Notify()这个过程,它一个接一个地调用IObservers列表中所有Observers的UpdateView()方法,什么意思呢,也就是说,一旦Notify()方法被调用了,所有注册了的Views(译者注:其实就是Observers)的UpdateView方法都会被自动触发。

下面看一下TObservable的源码:

TObservable = class(TInterfacedObject, IObservable)
private
    iObservers: TClassList;
    icurrentObject: TObject;
public
    constructor Create;
    destructor Destroy; override;
    procedure setCurrentObject(o: TObject);
    procedure RegObserver(observer: IObserver);
    procedure Notify(o: TObject);
    property CurrentObject: TObject read icurrentObject write icurrentObject;
end;
..
procedure TObservable.RegObserver(observer: IObserver);
begin
    if iObservers = nil then
    iObservers := TClassList.Create;
    iObservers.Add(TClass(observer));
end;
procedure TObservable.Notify(o: TObject);
var
    i: integer;
    observer: IObserver;
begin
    if iObservers = nil then exit;
    if o = nil then exit;
    self.setCurrentObject(o);
    for i := 0 to iObservers.Count - 1 do
    begin
        observer := IObserver(iObservers.Items[i]);
        observer.UpdateView(o);//trigger the UpdateView function of IObserver
    end;
end;

 

3.2. MVC

 

   3.2.1 What’s MVC?

 

   目前为止,大家应该知道了什么是Observer pattern(观察者模式)了,现在,开始讲一下什么是MVC。

我们先回顾一下Observers,根据我们所知的,Observer pattern主要包括两个主体,Observers和Observable Objects,所有的Observers首先必须注册到ObservableObject,如此,当在Observable Object中有数据更改时,所有的注册了的Observers也将被修改,那么,是谁负责注册这些Observers。

我认为,你应该可以认识到一些Observer模式的规则,那些注册了的Observers可以在ObservableObject中查询状态,也可以在那些状态的基础上更新它们,很明显,这不是十分的完美,我们需要更多的与现实情况进行交流,譬如,在Observer上点击一个按钮来让Observable做一些事,点击另一个按钮或者菜单,让它做另一件事。

让我们来对Observer模式进行一点改进,加入另一个小家伙,赋予它在Observers和Observable Objects之间控制注册和交流的职责。正因为它做的都是控制的工作,所以,我们命名它为Controller。

为了与Observer模式区分开来,我们将Observer命名为View,把Observable Objects命名为Model。

大家来看一下,至此,我们所拥有的一切,Model,View和Controller,这就是MVC。

答案揭晓:MVC是很简单的,就因为Observer模式有了一个Controller!。

 

   3.2.2 MVC in eMVC framework

 

MVC

   Figure3.3是在eMVC框架下定义的类模型,这里,我并没有把TObservable改为TModel,把IObserver改为IView,正如此,一种设计可以被两种模式所用。当然,读者只要知道Observer是View,Observable是Model,就足够了。

 

   3.2.3 MVC set

 

   大家都知道在eMVC中引入了一个概念MVC Set(mset)。

 

   1)What is it?

         一个mset必须有一个Controller且只有一个,它包含有一个(要求有一个)或者多个Models,每个Model有一个或多个注册了的Views

         一个mset能够完成独立的函数,它在基于eMVC开发的应用程序中被看成是可重复使用的最小的单元。

         mset

 

   2)How many msets can be there in an eMVC based application?

         至少一个,mset的数量取决你的应用程序有多复杂和你怎样去组织这些msets。

 

   3)How these msets organized together?

         基于eMVC开发的应用程序里的msets是在职责链模式中被组织起来的。

 

3.3. Chain of Responsibility

 

    3.3.1 What’s CoR?

 

    对于Chain of Responsibility(CoR)模式最经典的诠释是在GoF(Gang ofFour:四人组,作者是四个人:Erich Gamma、Richard Helm、Ralph Johnson 和 JohnVlissides)的《Design Patterns: Elements of Reusable Object-OrientedSoftware》一书中,其讲到:

“Avoid coupling the sender of a request to its receiver by givingmore than one object a chance to handle the request. Chain thereceiving objects and pass the request along the chain until an objecthandles it.”

痛苦啊,原文不好解释,下面讲解下这个模式的大体意思

“对于发送的请求,传递给不止一个对象去处理,那么这些对象连成一条链,请求是沿着这条链传递的,直到有一个对象处理它”

UML of CoR

典型的结构可能如Figure 3.5

CoR object structure

从上述的图片,我们可以总结如下:

1) 可能有很多对象有能力去处理传递来的请求,但只有一个对象实际地区处理那个请求。

2) 所有的对象形成一个队列,一个对象只知道它所连接的下一个对象(通过指针指向)。

3) 发送请求的对象不知道有多少对象有能力处理它的请求,它也不知道最后谁去处理了。

4) 发送请求的对象不能够控制接受请求的对象。

5) 能处理请求的对象可能是指定的一些能处理请求的对象中动态的形成链。

6) 改变接受请求者不会对放松请求者代码产生影响。

 

    3.3.2 CoR in eMVC

    在CoR模式里,接受请求的对象只管接受请求,在MVC模式里,一个Controller也负责处理一些请求。我们可以把他们二者结合到一起吗?当然,我们是可以做到的。

  在MVC里,Controller实现了一个sendCommand()方法,它还有另外一个名字叫HandleRequest(),这个名字来自于标准的CoR,这也说明了所有的Controllers也是可以接受请求的,也就意味着Controller在CoR模式里可以把所有的mset组织起来。

    3.3.3 ControlCenter

   1) What is ControlCenter?

       在我告诉你什么是ControlCenter之前,我们必须先来查找一些在标准的Delphi应用程序里的应用程序变量,在Delphi的帮助文档里,我们可以看到如下:

‘Each GUI application automatically declares an Application variable as the instance of
the application. If the Delphi application is not a Web server application, control panel
applet, or NT service application, this variable is of type TApplication.’

‘每一个图形界面的应用程序都会自动声明一些应用程序变量,来实例化应用程序,如果这个Delphi应用程序不是网页服务器程序、控制面板里的小程序、NT服务程序那么,这些变量的类型是TApplication’

下面是一个标准Delphi工程文件

program Project1;
uses
    Forms,
    Unit1 in ‘Unit1.pas’ {Form1};
{$R *.res}
begin
    Application.Initialize;
    Application.CreateForm(TForm1, Form1);
    Application.Run;
end.

应用程序是一个应用程序级的变量,它用于控制Delphi图形界面应用程序,很绕口,是不是?

在eMVC中,一个新建的类TControlCenter被用来接管TApplication。对于每个基于eMVC的应用程序,TControlCenter的一个实例ControlCenter会被自动声明出来。

这儿有一个基于eMVC的Delphi工程文件,与标准的Delphi工程定义有什么不同之处?在begin…end里有什么不一样的地方。

program NewMVCApp;
uses
    Forms,
    patterns,//include eMVC define unit
    MainCtrl in ‘MainCtrl.pas’,
    MainMdl in ‘MainMdl.pas’,
    MainView in ‘MainView.pas’ {ViewMain};
{$R *.res}
begin
    ControlCenter.Run;
end.

ControlCenter隐藏了应用程序变量,并不是把它除去了,在给予eMVC的应用程序里,你任然可以在任何地方任何时候来使用那些变量,就像在标准的Delphi工程里一样。

   2) How to register a new defined controller to ControlCenter?

        这是很简单的一件事,在每一个Controller的初始化部分调用ControlCenter的regController()函数

initialization
    ControlCenter.RegController(TControllerMain.Create); //register to ControlCenter

   3) Who in charge of release the registered controllers?

       这个大家不用担心,当应用程序结束的时候,ControlCenter将自动释放掉注册了的Controllers。

3.4. What else?

     除了上面的那些知识,我们还需要了解哪些别的东西吗?当然,设计模式不仅仅就这么些,如果你掌握的其他的设计模式,那么对于你平时的开发是十分有帮助的,不过,你得花点时间去学习,机可以再去看看这么三种模式:Template,CommandSingleton

4. The Core Components

其实eMVC框架包括了很少量的基础类,我们不需要什么了解这些类是怎么工作的,只需要用这个框架来做事就OK了,如下 Figure 4.1展示了核心构件,我们需要了解下的。

eMVC framework

核心构件的eMVC库:

  • TController
  • IObservable接口和TObservable类
  • IObserve接口
  • TControlCenter类
  • TCommand类
4.1. TController

     TController只是一个模板类,不能够将它实例化的,只能继承它,因此Controller类的申明如下

type
TControllerTypical = class (TController)
protected
    Procedure DoCommand(Command: string; const args: string=”); override;
public
    Constructor Create;
    Destructor Destroy; override;
end;

之前我们应经知道了TController有两个角色,首先在MVC模式里扮演着Controller,在CoR模式里扮演着接受请求的角色。

4.1.1 To be a Controller

         Controller有两个主要的任务,首先是将所有的Views(译者注:Observer)注册到Model(译者注:ObserableObject),这一步是什么简单的。其次是Controller将控制Views与Model之间的交互操作,或者是与其他Controller之间的交流。

            A: TASK 1: Register View to Model

                这个任务必须得在每个独立的Controller的Create方法中完成。

Constructor TControllerMain.Create;
begin
      inherited;
      model := TModelMain.Create;
      Application.CreateForm(TViewMain, view);
      model.RegObserver(view); //register the view to model
end;

                 或者你有更多的View,不要经,你只要像上面一样调用Model的RegObserver方法就OK了。

             B: TASK 2: Logical control

                 Control是用于接收View那边传来的请求并与之交流,正因为如此,基于这些要求,Control才能要求它的Model(译者注:同一个mset中的Model)去发送一个请求给另一个Controller(译者注:另一个mset种的Controller)

                 话是这么说,但真的要去实现它就有些困难的。在Java中,有一些监听的接口事先定义好了的,当你需要一个类,这个类的作用是能够接受点击选取一个标准树节点事件,那么,你只要继承TreeSelectionListener接口,把你的类放在那个标准树的View的监听列表中去。之后,所有的点击选取标准树节点事件都会传递到你的类中去处理。

                  不幸的是,在Delphi中,没有这样的构件,目前为止,eMVC也没有提供,因此,我们得自己去做。

                 现在我将给大家一个例子,这个例子的作用在View上监听按钮点击事件。我在View上建立了两个TButton,Button1的Caption是’&Close’,Button2的Caption是’&About’.

                (译者注:在新建一个eMVC工程的时候会建立四个文件,一个是应用程序主题默认名类似于***APP还有就是MainCtrl:控制(Controller)类;MainMdl:模块(Model)类;MainView:视图(View)类)

                Step1: 添加一个公共函数setClickEvent(或者其它的名字你认为可以的)到你的View类中去

type
TViewMain = class(TFORM, IObserver)
      Button1: TButton;
      Button2: TButton;
private
      { Private declarations }
      procedure UpdateView(o: TObject); //from IObserver
public
      { Public declarations }
      procedure setClickEvent(AEventHandler: TNotifyEvent);
end;

                  下面是setClickEvent的实现部分

procedure TViewMain.setClickEvent(AEventHandler: TNotifyEvent);
begin
      button1.OnClick := AEventHandler;
      button2.OnClick := AEventHandler;
end;

                  Step2: 添加一个私有方法OnClick到你的Controller类中去

type
TControllerMain = class(TController)
      model: TModelMain;
      view: TViewMain;
Private
..
      Procedure OnClick(Sender: TObject); //
..
end;         

                  如下是OnClick的实现

Procedure TControllerMain.OnClick(Sender: TObject);
Begin
      If Sender is TButton then
      Begin
            If TButton(Sender).caption = ‘&Close’ then
                  View.close
            Else If TButton(Sender).caption = ‘&About’ then
                  Application.messageBox(‘About box’);
      End;
end;

                    Step3:

                      修改Controller构造体函数:新添一句’view.setClickEvent(OnClick);’

Constructor TControllerMain.Create;
begin
      inherited;
      model := TModelMain.Create;
      Application.CreateForm(TViewMain, view);
      model.RegObserver(view);
      view.setClickEvent(OnClick);
end;

                      现在,每一个按钮的点击事件都能够被Controller捕获了。

             C: A sample of controller class

unit MainCtrl;
interface
uses SysUtils, forms, buttons, classes, controls, patterns, MainMdl, MainView;
type
   TControllerMain = class (TController)
   model: TModelMain;
   view: TViewMain;
Private
   Procedure OnClick(Sender: TObject); //
protected
   Procedure DoCommand(Command: string; const args: string=”); override;
public
   Constructor Create;
   Destructor Destroy; override;
end;
implementation
Constructor TControllerMain.Create;
begin
   inherited;
   model := TModelMain.Create;
   Application.CreateForm(TViewMain, view);
   model.RegObserver(view);
   view.setClickEvent(OnClick);
end;
Destructor TControllerMain.destroy;
begin
   freeAndNil(model);
   inherited;
end;
Procedure TControllerMain.DoCommand(Command: string; const args: string=”);
begin
end;

Procedure TControllerMain.OnClick(Sender: TObject);
Begin
   If Sender is TButton then
   Begin
      If TButton(Sender).caption = ‘&Close’ then
      View.close
   Else If TButton(Sender).caption = ‘&About’ then
      Application.messageBox(‘About box’);
   End;
end;
initialization
ControlCenter.RegController(TControllerMain.Create); //register to ControlCenter end.

4.1.2 Be a handler

         要在责任链中担任一个接受请求的对象,首先Controller必须得进入到链中去,调用ControlCenter.RegController方法新添一个在外部已经定义好了的Controller,然后,Controller必须有能力从其他的Controller接受请求,不用说,它也能够发送请求,让我们来看些TController是怎么这样的工作的。

      A  Send Request

           在eMVC中,我们得调用请求命令,两种命令可以被使用,’String command’和’an object command’,可以再4.5中具体看下。

           发送一个命令式十分简单的。

            Step 1,

            在公共块中(Public)定义一个有意思的并且独一无二的常量字符创,两种命令都一样的。

            Step 2,

            使用SendCommand方法来发送命令,在TController中有5种重载的SendCommand方法,根据命令参数的不同,你可以参考下使用哪一个。

procedure SendCommand(ACommand: ICommand; const args: TObject = nil);
overload;
procedure SendCommand(ACommand: string); overload;
procedure SendCommand(ACommand: string; args: string); overload;
procedure SendCommand(ACommand: string; args: TObject); overload;
procedure SendCommand(ACommand: string; args: pointer); overload;

      B Handler Request

          重载的DoCommand方法源自TController.

         如果你想要它接受对象命令,重载的形式如下:

Procedure DoCommand (ACommand: ICommand; const args: TObject = nil);

          如果你想要它接受不带参数的字符串命令,重载的形式如下:

Procedure DoCommand (ACommand: string);

         如果你想要它接受带参数的字符串命令,重载的形式如下:

Procedure DoCommand (ACommand: string; const args: string = ”);
Procedure DoCommand (ACommand: string; const args: TObject = nil);
Procedure DoCommand (ACommand: string; const args: pointer = nil);

4.2. IObservable and TObservable

TObservable 是IObservable借口的默认实现,它类似于MVC模式里的MODEL

普遍情况下,我们推荐所有新建的Model类都源自TObservable,这儿有一个新建Model的定义。

unit MainMdl;
interface
uses Classes, forms, SysUtils, patterns;
type
      TModelMain = class(TObservable)
public
      constructor Create;
      destructor Destroy; override;
end;
implementation
constructor TModelMain.Create;
begin
end;

4.2.1 What’s the task of the modal?

Task 1: Work for Controller

当Controller截获到View的事件时,它将会叫Model去处理,譬如计算处理数据库里的数据,换句话说,就是Model必须提供一系列的方法函数去应付Controller。

Task 2: Prepare and provide ‘Bullet’ for the View

所有在Views上显示的东西(数据之类的)都来自Model。

4.2.2 How to notify?

TObservable有一个方法Notify(O: TObject),当你想要更新所有注册了的Views的时候调用这个方法就可以实现。

4.2.3 What to notify?

在TObservable的Notify(O: TObject)方法里有一个TObject类型的参数,这个字符串包含一些数据,这些数据可能来源于TObject的任何类。

4.2.4 What happened after I triggered the Notify method?

可以参见4.5章节 IObserver

4.3. IObserver interface

在开发一个eMVC应用程序中定义一个View是一份简单的差事,只要实现IObserver接口。

View的原型可以是TForm,TFrame,TPanel,TTreeView或者其他的TWinControl祖宗类。

unit MainView;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, StdCtrls, ComCtrls, ExtCtrls,
Forms, patterns;
type
      TViewMain = class(TFORM, IObserver)
private
{ Private declarations }
      procedure UpdateView(o: TObject);//from IObserver
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TViewMain.UpdateView(o: TObject);
begin
      {write your code here}
end;
end.

就如你在上面的源码中看见的一样,你只要关注一下这个方法,意思就是说每个View必须实现一个它自己的UpdateView方法。

4.4. TControlCenter

原则上,你不需要申明一个TControlCenter实例,eMVC会自动创建的。更多详情请参见3.3.3

4.5. TCommand

eMVC是一个命令驱动的框架,之前我提到过在eMVC中有两种命令‘string command‘和’object command‘。

4.5.1 Well, what’s Object Command?

首先,一个Object Command必须是继承于TObject的一个类。

TCommand默认是Object Command的实现,实际上,它是String Command的包装,但是,它比String Command更强大,更复杂

4.5.2 How to create an Object command?

Constructor Create (ACommand: string = ”; const AParam: Pointer = nil;
AParamObject: TObject = nil; AParamStr: string = ”;
Owner: TController = nil; ReleaseParam: Boolean = true);

这里,我强烈要求使用TCommand,当你需要一个Object Command的时候,如下:

Cmd := TCommand.Create(CMD_DO_SOMETHING);

CMD_DO_SOMETHING是预先定义好了的字符串常量,但有的时候,它是不能满足需求的,当一个Controller掌控这个的时候,就需要更多额外的信息。

我们可以从上面的TCommand结构代码中看到有这么些参数

  • ACommand:当你创建一个TCommand实例的时候,一个独一无二的String Command是必须的,它不能使空的,这是在构造方法中唯一重要的参数
  • AParam:一个记录指针,包含了很多有意义的信息,这些信息是命令在执行过程中需要的。
  • AParamObject:与AParam参数很类似,但是它是TObject的一个实例。
  • AParamStr:一个字符串参数。
  • Owner:发送这个命令的Controller。
  • ReleaseParam:在Delphi中,所有的对象在不需要的时候都得被释放,这也是ObjectCommand做的事情,如果ReleaseParam设置为true,在Controller队列中的最后一个Controller将把ObjectCommand释放掉,否则,你将手动释放,要不然会产生内存溢出。可以查看4.1.2获取更多的信息。

5. Installing the Library

目前为止,eMVC支持Delphi 5/6/7/2005/2006,下载好一个zip包后,解压出来,放到一个文件夹里,最好放到Delphi安装目录下,容易找到。我下载的是eMVC_1.0a3,解压出来有三个文件夹。

  • Sample:包含了eMVC的一些例子
  • src:所有的eMVC源码
  • doc:一些关于eMVC的文档
5.1. Delphi 5

“File->Open”在解压出来的src打开EasyMVC_D5.dpk,在“Package…”点击”Compile”按钮,然后“Install”,最后配置下Library,点击”Tools->EnvironmentOptions…”把src路径加入到library path,然后OK。

5.2. Delphi 6

 “File->Open”在解压出来的src打开EasyMVC_D6.dpk,在“Package…”点击”Compile”按钮,然后“Install”,最后配置下Library,点击”Tools->EnvironmentOptions…”把src路径加入到library path,然后OK。

5.3. Delphi 7

 “File->Open”在解压出来的src打开EasyMVC_D7.dpk,在“Package…”点击”Compile”按钮,然后“Install”,最后配置下Library,点击”Tools->EnvironmentOptions…”把src路径加入到library path,然后OK。

5.4. Delphi 2005

“File->Open”在解压出来的src打开EasyMVC_D2005.bdsproj,在ProjectManage(默认情况下,是在Delphi2005右上角),右击’EasyMVC_D2005.bpl‘,点击install,最后配置下Library,点击”Tools->Options”,在配置窗体中选择”Enviroment Options->DelphiOptions->Library-Win32”,把src路径加入到library path,然后OK。

5.5. Delphi 2006

“File->Open”在解压出来的src打开EasyMVC_D2006.bdsproj,在ProjectManage(默认情况下,是在Delphi2005右上角),右击’EasyMVC_D2006.bpl‘,点击install,最后配置下Library,点击”Tools->Options”,在配置窗体中选择”Enviroment Options->DelphiOptions->Library-Win32”,把src路径加入到library path,然后OK。