2012-11-01 89 views
3

由于与我想在我的TRemotable类中使用泛型相关的问题没有真正相关。我发现Soap.OPToSOAPDomConv.pas有一些问题。它使用旧的RTTI,我猜不能处理泛型,所以类不会被序列化为xml。TREMotable类中的Delphi XE2泛型

我设法改变Soap.OPToSOAPDomConv.pas,以便它可以与泛型一起使用。我的主要问题是,如果认为在Delphi源文件中进行更改可以吗? 如果不是,有没有更好的方法来做到这一点?只要它只是我使用它,我想没有什么大问题,但很难将源代码分发给其他人,并且德尔福也会考虑未来的变化。 这个lenghty后剩下的只是细节什么我实际上做:-)

我在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); 

为:(不最漂亮的实现我猜)

在程序中新的变量:

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服务导入的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; 

要:

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。如果是我的话,如果我改变它的话,我会希望对这段代码进行单元测试。 –

+0

@Warren。谢谢,关于SOAP Remoting代码的好处。我觉得这有点胆大妄为...我真的不明白你在远程处理它们之前序列化泛型(我刚刚了解泛型),你能解释一下吗?我基本上没有任何理由,除了缩减代码量以及对RTTI空间没有耗尽的范围。 – dahook

+0

而不是远程TGenericList ,远程存储在字符串参数中的TLCARS的JSON字符串。 –

回答

1

有两件事情进行修改时,考虑本等。首先,变化是否会影响现有的功能。在这种情况下,我会说它是安全的,因为这个操作的功能是新的,所以不应该有任何意外的行为。 第二部分是进化发展环境。环境演变的问题在于动作之间的绑定可能会改变,并可能导致意想不到的事情。在这一刻,假设XE2拥有更新的份额是正确的。如果不这样做,那么在修补或更新时就必须保持密切关注。第二种类似XE2到XE3的变化可以更好地处理。只需将以下内容放在Soap.OPToSOAPDomConv的顶部。PAS

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

当在编译时你可能会依稀记得,有一些关于该文件... 因此,在短期得到错误,这不是坏事,只要尝试评估影响和适应环境变化。希望这是你想知道的。