For reasons not really relevant to the question I want to use generics in my TRemotable classes. I've found that Soap.OPToSOAPDomConv.pas has some problems with this. It's using the old RTTI which I guess can't handle generics so the classes is not serialized into xml.
I've managed to change Soap.OPToSOAPDomConv.pas so that it works with generics. My main question is if it is considered ok to do changes in the Delphi source files? If it isn't, is there a better way to do this? As long as it's just me using it I guess there is no big problems, but it's hard to distribute the source to others, and then there's also future changes in Delphi to consider. The rest of this lenghty post is just details about what I'm actually doing :-)
I've changed this in Soap.OPToSOAPDomConv.pas (row 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: (not the prettiest implementation I guess)
New variables in the procedure:
Context: TRttiContext;
RttiProperty: TRttiProperty;
Row 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;
Some details as to what I am doing is probably helpful. The background is that the imported wsdl from the SOAP Web Service generates a huge unit, that consists of about 2000 classes and 300k rows of code. The web service design is out of my control. The WSDL Importer makes all of these classes visible in RTTI, which consumes the RTTI space and the unit won't compile.
I've refactored the code here and there and now have a working implementation. While refactoring I found that I could cut away some 50000 rows of redundant code by using generics. Since Delphi won't compile the imported wsdl "as is" anyway I will have to maintain the unit manually whenever new methods becomes available in the web service, so I want to make it as readable as possible.
Basically I'm changing according to below. The sample has very simplified classes, and the sample actually has more lines in the refactored code, but considering the original classes has a lot of procedures etc this method really makes the unit a lot more readable, and it's also easier to compose the classes.
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;
Kind Regards,
Dan