2014年5月12日星期一

TObject.Create is not a virtual method

DataSnap在创建服务方法类的时候,如果从TPersistent继承写服务方法,不写DSServerClass的DSServerClass1CreateInstance事件,是会有问题

比如我定义一个服务方法
 
  {$METHODINFO ON}
  TServerMethod = class(TPersistent)
  public
    constructor Create; virtual;
    destructor Destroy; override;
  end;
  {$METHODINFO OFF}

由于TObject.Create不是虚方法,在使用
var
  ClassRef: TTPersistentClass;
  M: TServerMethod;
begin
  ClassRef := TServerMethod;
  M := ClassRef.Create; //这里有问题,这个的Create,不会call到TServerMethod.Create,只会call TObject.Create,也就是啥也没干
end;
请看代码
function TDSServerConnectionHandler.CreateInstance(const ServerClass: TDSCustomServerClass; const DsClass: TDSClass): TObject;
var
  Instance: TObject;
begin
  if ServerClass <> nil then
  begin
    FCreateInstanceEventObject.ServerClassInstance := nil;
    ServerClass.CreateInstance(FCreateInstanceEventObject); //如果没有实现DSServerClass1CreateInstanc事件,这里的FCreateInstanceEventObject.ServerClassInstance会是nil
    Instance := FCreateInstanceEventObject.ServerClassInstance;
    if Instance <> nil then
      Exit(Instance);
  end;
  Result := DsClass.CreateInstance;//所以会走到这里
end;

function TDSClass.CreateInstance: TObject;
var
  AdapteeInstance: TObject;
  Component: TComponent;
begin
  if Assigned(FClassRef) then
  begin
    if Assigned(FAdapteeClass) then
    begin
      AdapteeInstance := FAdapteeClass.CreateInstance;
      Result := TDSAdapterClassType(FClassRef).Create(AdapteeInstance);
    end
    else
    begin
      if FClassRef.InheritsFrom(TComponent) then
      begin
        // Allows Forms and DataModules to read in the components
        // they contain.
        //
        Component := FClassRef.NewInstance as TComponent;
        Component.Create(nil);
        Result := Component;
      end
      else
        Result := FClassRef.Create//然后再走到这里,FClassRef是一个TTPersistentClass,它的Create,不会触发TServerMethod.Create
    end;
  end
  else
    Result := nil;
end;

郁闷吧,TObjec.Create不是虚方法多少年前都已经讨论过,自然有它的道理。 要解决这个问题,用上面对待TComponent方法来做可以,这样的方法其实在TApplication.CreateForm里面也用到了。
        //Result := FClassRef.Create//然后再走到这里,FClassRef是一个TTPersistentClass,它的Create,不会触发TServerMethod.Create
        //修改为,先定义一个TServerMethod的变量,再NewInstance再Create,再赋值。        

没有评论:

发表评论