由于与我想在我的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;
亲切的问候,
丹
哇。勇敢。为什么不只是序列化你的泛型,然后将它们远程控制,有什么原因吗?由于SOAP Remoting代码通常是由想要解决其错误的人修复和更新的,因此改变它并重建它并不是问题,因为它将更改System.pas。如果是我的话,如果我改变它的话,我会希望对这段代码进行单元测试。 –
@Warren。谢谢,关于SOAP Remoting代码的好处。我觉得这有点胆大妄为...我真的不明白你在远程处理它们之前序列化泛型(我刚刚了解泛型),你能解释一下吗?我基本上没有任何理由,除了缩减代码量以及对RTTI空间没有耗尽的范围。 – dahook
而不是远程TGenericList,远程存储在字符串参数中的TLCARS的JSON字符串。 –