Delphi XE2中TRemotable类的泛型应用

3
由于问题与问题本身不相关,我想在我的TRemotable类中使用泛型。但我发现Soap.OPToSOAPDomConv.pas存在一些问题。它正在使用旧的RTTI,我猜测无法处理泛型,因此该类未序列化为xml。
我已经成功更改了Soap.OPToSOAPDomConv.pas以便支持泛型。我的主要问题是,在Delphi源文件中进行更改是否被认为是可以接受的? 如果不行,有更好的方式吗?只要我自己使用它,我想没有大问题,但很难将源代码分发给他人,而且还需考虑Delphi未来的变化。 这篇冗长的文章的其余部分只是关于我实际在做什么的细节 :-)
我已更改Soap.OPToSOAPDomConv.pas(第3759行)。
if SerializeProps then
begin
  { Serialized published properties }
  Count := GetTypeData(Instance.ClassInfo)^.PropCount;
  if Count > 0 then
  begin
    CheckedElemURI := False;
    GetMem(PropList, Count * SizeOf(Pointer));
    try
      GetPropInfos(Instance.ClassInfo, PropList);

To: (我猜这不是最好的实现方式)

过程中的新变量:

Context: TRttiContext;       
RttiProperty:  TRttiProperty;

第3759行:

if SerializeProps then
begin
  { Serialized published properties }
  Count := 0;
  for RttiProperty in Context.GetType(Instance.ClassInfo).GetProperties do
  begin
    if RttiProperty.Visibility = mvPublished then //The old method only read published
      Count := Count + 1;                         //RTTI scoping [mvPublished] requires changes to
  end;                                            //soap.InvRegistry
  begin
    CheckedElemURI := False;
    GetMem(PropList, Count * SizeOf(Pointer));
    try
      I := 0;
      for RttiProperty in Context.GetType(Instance.ClassInfo).GetProperties do
        if RttiProperty.Visibility = mvPublished then
        begin
          PropList[I] := TRttiInstanceProperty(RttiProperty).PropInfo;
          I := I + 1;
        end;

提供一些我正在做的细节可能会有帮助。背景是,从SOAP Web Service导入的wsdl生成了一个巨大的单元,由大约2000个类和300k行代码组成。Web服务设计不在我的控制之下。 WSDL导入程序使所有这些类在RTTI中可见,这会消耗RTTI空间,而且该单元将无法编译。

我已经对代码进行了重构,并且现在有一个可工作的实现。在重构时,我发现可以通过使用泛型来削减约50000行冗余代码。由于Delphi无论如何都不会编译导入的wsdl“原样”,因此每当Web服务中有新方法可用时,我都必须手动维护该单元,因此我希望尽可能使其易读。

基本上,我正在按照以下方式进行更改。示例具有非常简化的类,并且实际上在重构后的代码中有更多行,但考虑到原始类具有许多过程等,此方法确实使单元更加易读,并且还更容易组合类。

TLCar = class(TRemotable)
private
  FEngine: string;
  FName: string;
published
  property Name: string read FName write FName;
  property Engine: string read FEngine write FEngine;
end;

TLBicycle = class(TRemotable)
private
  FPedals: string;
  FName: string;
published
  property Name: string read FName write FName;
  property Pedals: string read FPedals write FPedals;
end;

TListCarRequest = class(TRemotable)
private
  FreturnedTags: TLCar;
published
  property returnedTags: TLCar read FreturnedTags write FreturnedTags;
end;

TListBiCycleRequest = class(TRemotable)
private
  FreturnedTags: TLBicycle;
published
  property returnedTags: TLBicycle read FreturnedTags write FreturnedTags;

To:

TCommonReturnedTags = class(TRemotable)
private
  FName: string;
published
  property Name: string read FName write FName;
end;

TLCar = class(TCommonReturnedTags)
private
  FEngine: string;
published
  property Engine: string read FEngine write FEngine;
end;

TLBicycle = class(TCommonReturnedTags)
private
  FPedals: string;
published
  property Pedals: string read FPedals write FPedals;
end;

TGenericListRequest<T: TCommonReturnedTags, constructor> = class(TRemotable)
private
  FreturnedTags: T;
published
  property returnedTags: T read FreturnedTags write FreturnedTags;
end;

TListCarRequest = class(TGenericListRequest<TLCar>)
end;

TListBiCycleRequest = class(TGenericListRequest<TLBicycle>)
end;

亲切问候,

2
哇,真勇敢。你不直接序列化泛型然后再进行远程操作,有什么原因吗?由于SOAP Remoting代码通常由想要解决其错误的人修复和更新,因此更改并重新构建它并不会带来太多问题,而更改System.pas则可能会带来问题。如果是我,我会在更改代码时希望对其进行单元测试覆盖。 - Warren P
@Warren。谢谢,你提到SOAP Remoting代码的观点很好。我也觉得这有点大胆...我不太明白你所说的在远程之前序列化泛型(我刚学习泛型),你能再解释一下吗?我的基本理由只是为了缩小代码量以及将作用域限定在RTTI空间不会耗尽。 - dahook
不要远程传输TGenericList<TLCar>,而是远程传输存储在字符串参数中的TLCARS的JSON字符串。 - Warren P
@Warren。好的,谢谢。恐怕这有点超出我的能力范围了(我不知道从哪里开始... :-))我想我会坚持使用“正常”的类定义,只是将子类隐藏在其中。然后,只需剪切并粘贴wsdl导入程序生成的单元,以限制子类的范围。虽然耗时且乏味,但似乎可以工作。 - dahook
1个回答

1

进行修改时需要考虑两个方面。首先,更改是否会影响现有功能。在这种情况下,我认为是安全的,因为该功能对于此操作是新的,所以不应出现任何意外行为。 其次是演变开发环境。开发环境演变的问题在于,操作之间的绑定可能会发生变化,这可能会导致意外的结果。此刻可以假设XE2已经拥有了更新。如果没有,则在打补丁或更新时必须密切注意。第二种更改(如从XE2到XE3)可以更好地处理。只需将以下内容放在Soap.OPToSOAPDomConv.pas的顶部:

{$IFNDEF VER230}
   {$MESSAGE ERROR 'Intended to be used with XE2'}
{$ENDIF}

当编译时出现错误时,您可能会模糊地记得有关该文件的某些内容... 因此,总的来说,只要尝试评估影响并适应环境变化,就不是坏事。希望这就是您想知道的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接