2011年10月20日星期四

datasnap的进阶 TDSServerClass

TDSServerClass这个控件是很简单,最熟悉不过的是下面的代码,它的OnGetClass事件里加上我们的服务器方法类
procedure TServerContainer1.DSServerClass1GetClass(
  DSServerClass: TDSServerClass; var PersistentClass: TPersistentClass);
begin
  PersistentClass := ServerMethodsUnit1.TServerMethods1;
end;
问题是:一般的真实应用里,我们的服务方法类会有很多,岂不是要在TServerContainer里面放很多个 TDSServerClass??? 并且还要去写它的OnGetClass类方法

要想解决这个问题,我们还是的理解TDSServerClass到底是干嘛的,为啥EMBT这么设计了。

datasnap里面,TDSServer是老大,它靠TDSTCPServerTransport来负责通讯, 至于根据通讯来触发的什么服务器方法,就靠TDSServer了。TDSServer将它所拥有的TDSServerClass的TPersistentClass的服务方法都给存起来,代码在
DSCommonServer.pas的
procedure TDSServerMethodProvider.AddRegisteredServerClasses;
var
  List: TDBXArrayList;
  Index: Integer;
  Count: Integer;
  ServerClass: TDSCustomServerClass;
  ClassInfo: TDSClassInfo;
  DsClass: TDSClass;
  AdapteeClass: TDSClass;
  ClassName: UnicodeString;
begin
  List := TDBXArrayList.Create;
  try
    FServer.GetServerClassList(List);//取得DSServer关联着的TDSServerClass列表
    Count := List.Count;
    for index := 0 to Count - 1 do
    begin
      ServerClass := TDSCustomServerClass(List[Index]);
      DsClass := ServerClass.DSClass; //这里触发了通过GetDSClass函数触发OnGetClass事件
      ClassName := DsClass.DSClassName;
      AdapteeClass := DsClass.AdapteeDSClass;
      if AdapteeClass <> nil then
        ClassName := AdapteeClass.DSClassName;
      ClassInfo := TDSClassInfo.Create;
      ClassInfo.ServerClass := ServerClass;
      ClassInfo.DSClassName := ClassName;
      ClassInfo.LifeCycle := ServerClass.LifeCycle;
      ClassInfo.RoleName := ServerClass.RoleName;
      ClassInfo.DSClass := DsClass;
      AddServerClass(ClassInfo);//存起来
      AddAllMethods(ClassInfo); //存起来
    end;
  finally
    FreeAndNil(List);
  end;
end;

进一步查看代码知道,TDSServerClass的GetDSClass是可以重载的
function GetDSClass: TDSClass; override;
因此,如果我们自己要写很多服务方法类时,可以自己写一个注册服务方法的类,也就是直接覆盖GetDSClass就可以了,那样就不必写什么OnGetClass事件并去关联事件(这里另一个想法是,要关联事件,直接用匿名函数去关联,这样就不必为了关联而单独定义一个类方法,但是匿名函数只是一个方法,而不是对象方法,也要让MakeObjectInstance反向?等几天测测)。

简单的代码如下
{$METHODINFO ON} 
TMyServerMethod = class
end;
{$METHODINFO OFF}
TServerMethodA = class(TMyServerMethod )
   function ServerMethodA1: Integer;
   function ServerMethodA2: Integer;   
end; 

TServerMethodB = class(TMyServerMethod)
   function ServerMethodB1: Integer;
   function ServerMethodB2: Integer;   
end;

TMyDSServerClass=class(TDSServerClass)
  private
    FPersistentClass: TPersistentClass;
  protected
    function GetDSClass: TDSClass; override;
  public
    constructor Create(AOwner: TComponent; AServer: TDSCustomServer; AClass: TPersistentClass); reintroduce;overload;
  end;

constructor TMyDSServerClass.Create(AOwner: TComponent; AServer: TDSCustomServer; AClass: TPersistentClass);
begin
  inherited Create(AOwner);
  FPersistentClass := AClass;
  Self.Server := AServer;
end;

function TMyDSServerClass.GetDSClass: TDSClass;
begin
  Result := TDSClass.Create(FPersistentClass, False);
end;

然后,我们要注册服务方法类时,写个注册函数
procedure RegisterServerClasses(AOwner: TComponent; AServer: TDSServer);
begin
  TMyDSServerClass.Create(AOwner, AServer, TServerMethodA );
  TMyDSServerClass.Create(AOwner, AServer, TServerMethodB);
end;

有了这个函数,我们以后写代码,就可以自己专注写服务方法类,写完了再在这里增加一行代码就行了,代码不用拥挤到一个ServerContainerUnit1里,不好维护。

当然,DSServer还有LifeCycle的属性,可以添加后,覆盖CreateInstance和DestroyInstance两个方法


没有评论:

发表评论