我可以对从Delphi 2010中的wsdl导入类派生的类实现更改跟踪吗?
有没有办法在派生类中实现更改跟踪而不覆盖基类的getter和setter?
我在开发中有一个基于实体框架的多层项目,数据访问和业务逻辑最终转移到基于C#的服务器应用程序. (数据访问已经迁移)客户端在Delphi 2010中. 我已经使用数据传输对象在客户端和服务器之间传递信息,但是有必要从Delphi实现我自己的更改跟踪.我最初是通过继承wsdl中的Dtos并“覆盖”getter和setter来实现的. wsdl import中的基类(无法真正控制): // ************************************************************************ // // XML : DtoCONTAINER_JNL,global,<complexType> // Namespace : http://k3scs.com/WCF // ************************************************************************ // DtoCONTAINER_JNL = class(DtoBase) private FJNL_ID: Integer; FJNL_TYPE_ID: Integer; FJNL_DATE: TXSDateTime; published property JNL_ID: Integer read FJNL_ID write FJNL_ID; property JNL_TYPE_ID: Integer read FJNL_TYPE_ID write FJNL_TYPE_ID; property JNL_DATE: TXSDateTime read FJNL_DATE write FJNL_DATE; 派生类: TDtoCONTAINER_JNL = class(DtoCONTAINER_JNL,IDto) private FName : string; FReferenceCounted : boolean; _isNew : boolean; FModified : boolean; FJNL_ID : integer; FJNL_TYPE_ID : integer; FJNL_DATE : TDateTime; public property JNL_ID : integer read FJNL_ID write SetJNL_ID; property JNL_TYPE_ID : integer read FJNL_TYPE_ID write SetJNL_TYPE_ID; property JNL_DATE : TDateTime read GetJNL_DATE write SetJNL_DATE; 典型的setter方法: procedure TDtoCONTAINER_JNL.SetJNL_DATE(const value : TDateTime); begin ChangedProperties:= DtoGenerics.ChangeTracker('JNL_DATE',value,inherited JNL_DATE,self.IsLoaded,ChangedProperties); inherited JNL_DATE := DtoGenerics.GetXsDate(value); end; 典型的吸气方法: function TDtoCONTAINER_JNL.GetJNL_DATE : TDateTime; begin Result := DtoGenerics.GetDate(inherited JNL_DATE); end; 无论何时设置属性,更改跟踪器都会将此属性名称添加到已更改属性的列表中以返回到服务器.这样可以使更新语句具有针对性和高效性.问题是每个getter / setter实际上使得派生类与base不兼容,也就是说,多态性被破坏,并且cast不再按预期工作. 编辑 Wsdl导入器主要由使用字符串格式的常量或类似的东西组成,以创建复杂类型的Delphi等价物.我做了以下更改,使用类似的常量名称来轻松识别我的更改,以及将它们放在与预先存在的代码相关的位置. // In WSDLImpConst // I changed sRemoteClassDeclPas constant value of 'private' to 'proctected' // Then I added these after SUnitInit sTrackerDec = sTrackerProcPrefix+ sTrackerProcArgs + sLineBreak; sTrackerProc = sTrackerDec + 'begin' + sLineBreak + ' Result:= nProps;' + sLineBreak + ' if (_loaded) and (oVal <> pVal) then' + sLineBreak + ' begin ' + sLineBreak + ' Result := TrackChange(pName,nProps);' + sLineBreak + ' end;' + sLineBreak + 'end;' + sLineBreak ; sTracker2Dec = sTrackerProcPrefix+ sTracker2ProcArgs + sLineBreak; sTracker2Proc = sTracker2Dec + 'begin' + sLineBreak + ' Result:= nProps;' + sLineBreak + ' if (_loaded) and (oVal <> DateTimeToXSDateTime(pVal)) then' + sLineBreak + ' begin ' + sLineBreak + ' Result := TrackChange(pName,nProps);' + sLineBreak + ' end;' + sLineBreak + 'end;' + sLineBreak ; sTracker3Dec = sTrackerProcPrefix+ sTracker3ProcArgs + sLineBreak; sTracker3Proc = sTracker3Dec + 'begin' + sLineBreak + ' Result:= nProps;' + sLineBreak + ' if nProps = '''' then' + sLineBreak + ' nProps := pName' + sLineBreak + ' else' + sLineBreak + ' nProps := pName + '','' + nProps;' + sLineBreak + ' Result:= nProps;' + sLineBreak + 'end;' + sLineBreak ; sTracker4Dec = sTrackerProcPrefix+ sTracker4ProcArgs + sLineBreak; sTracker4Proc = sTracker4Dec + 'begin' + sLineBreak + ' Result:= nProps;' + sLineBreak + ' if (_loaded) and (oVal <> pVal) then' + sLineBreak + ' begin ' + sLineBreak + ' Result := TrackChange(pName,nProps);' + sLineBreak + ' end;' + sLineBreak + 'end;' //Added my own setters: sRemoteClassSetterImplPas = 'procedure %0:s.Set%1:s(const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + 'end;' + sLineBreak; sRemoteClassSetterImplPas2= 'procedure %0:s.Set%1:s(const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + ' F%1:s_Specified := True;' + sLineBreak + 'end;' + sLineBreak; sRemoteClassSetterImplPas3 = 'procedure %0:s.Set%1:s(const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' ChangedProperties:= TrackChange(''%1:s'',A%2:s,F%1:s,ChangedProperties);' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + 'end;' + sLineBreak; sRemoteClassSetterImplPas4 = 'procedure %0:s.Set%1:s(const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' ChangedProperties:= TrackChange(A%2:s,''%1:s'',ChangedProperties);' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + 'end;' + sLineBreak; // And for indexed properties sRemoteClassSetterImplPasIdx2= 'procedure %0:s.Set%1:s(Index: Integer; const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + ' F%1:s_Specified := True;' + sLineBreak + 'end;' + sLineBreak; sRemoteClassSetterImplPasIdx3 = 'procedure %0:s.Set%1:s(Index: Integer; const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' ChangedProperties:= TrackChange(''%1:s'',ChangedProperties);' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + 'end;' + sLineBreak; sRemoteClassSetterImplPasIdx4 = 'procedure %0:s.Set%1:s(Index: Integer; const A%2:s: %2:s);' + sLineBreak + 'begin' + sLineBreak + ' ChangedProperties:= TrackChange(A%2:s,ChangedProperties);' + sLineBreak + ' F%1:s := A%2:s;' + sLineBreak + 'end;' + sLineBreak; // Added these before the SImplDecl constant: sIntfFactoryDecl = '_di_%0:s Get%0:s(bool useWSDL=false,AnsiString addr="",THTTPRIO* HTTPRIO=0);' + sLineBreak + sLineBreak; sTrackerProcPrefix = 'function TrackChange'; sTrackerProcArgs = '(const pName: string; pVal,oVal: variant; _loaded: boolean; nProps: string): string; overload'; sTracker2ProcArgs = '(const pName: string; pVal: TDateTime; oVal: txsdateTime; _loaded:boolean; nProps: string): string; overload;'; sTracker3ProcArgs = '(const pName: string; nProps: string): string; overload;'; sTracker4ProcArgs = '(pVal,oVal: TByteDynArray; const pName: string; _loaded: boolean; nProps: string): string; overload'; sIntfTrackDecl = sTrackerProcPrefix + sTrackerProcArgs+ sLineBreak; sIntfTrack2Decl = sTrackerProcPrefix + sTracker2ProcArgs+ sLineBreak; sIntfTrack3Decl = sTrackerProcPrefix + sTracker3ProcArgs+ sLineBreak; sIntfTrack4Decl = sTrackerProcPrefix + sTracker4ProcArgs+ sLineBreak; // Then in WSDLPasWriter I added my new constant arrays: SetterImpl2:array[Boolean] of string = (sRemoteClassSetterImplPas2,sRemoteClassSetterImplPasIdx2); SetterImpl3:array[Boolean] of string = (sRemoteClassSetterImplPas3,sRemoteClassSetterImplPasIdx3); SetterImpl4:array[Boolean] of string = (sRemoteClassSetterImplPas4,sRemoteClassSetterImplPasIdx4); // then modified the setter section in 'WriteComplexTypeClass' { Setter } if UseSetGets or GenSpecifiedSupport(Member) then begin if GenSpecifiedSupport(Member) then begin WriteFmt(SetterImpl2[HasIndexDecl(Member)],[WSDLType.LangName,Member.LangName,Member.DataType.LangName]) end else begin if (ContainsStr(BaseName,'Dto')) and (not ContainsStr(Member.DataType.LangName,'XS')) and (not ContainsStr(Member.DataType.LangName,'ArrayOf')) then if (ContainsStr(Member.DataType.LangName,'TByteDynArray')) then WriteFmt(SetterImpl4[HasIndexDecl(Member)],Member.DataType.LangName]) else WriteFmt(SetterImpl3[HasIndexDecl(Member)],Member.DataType.LangName]) else WriteFmt(SetterImpl1[HasIndexDecl(Member)],Member.DataType.LangName]); end; // at WriteInterfaceEnd I added WriteFmt(sIntfTrackDecl,[]); WriteFmt(sIntfTrack2Decl,[]); WriteFmt(sIntfTrack3Decl,[]); WriteFmt(sIntfTrack4Decl,[]); // at WriteInterfaceBegin I added WriteLn(sTrackerProc,[]); WriteLn(sTracker2Proc,[]); WriteLn(sTracker3Proc,[]); WriteLn(sTracker4Proc,[]); // finally I changed the wsdlImp dpr and replaced 'AnsiString' (or 'widestring' I can't remember) with 'string' 解决方法
如果我没弄错的话,WSDL to Delphi转换器源代码是Delphi企业及更高版本的一部分(在wsdlimporter目录中称为WSDLImp.dpr).
我会调整它直接生成自己的类. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |