Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以在Delphi2010中从wsdl导入的类派生的类上实现更改跟踪吗?_Delphi_Oop_Design Patterns_Delphi 2010 - Fatal编程技术网

我可以在Delphi2010中从wsdl导入的类派生的类上实现更改跟踪吗?

我可以在Delphi2010中从wsdl导入的类派生的类上实现更改跟踪吗?,delphi,oop,design-patterns,delphi-2010,Delphi,Oop,Design Patterns,Delphi 2010,有没有一种方法可以在不重写基类的getter和setter的情况下在派生类中实现更改跟踪? 我正在开发一个基于实体框架的多层项目,数据访问和业务逻辑最终转移到基于C#的服务器应用程序。(数据访问已迁移)客户端位于Delphi 2010中。 我使用数据传输对象在客户机和服务器之间传递信息,但是有必要从Delphi实现我自己的更改跟踪。我最初是通过从wsdl中的DTO继承并“覆盖”getter和setter实现的。 wsdl导入中的基类(对此没有实际控制): 典型的setter方法: procedu

有没有一种方法可以在不重写基类的getter和setter的情况下在派生类中实现更改跟踪?
我正在开发一个基于实体框架的多层项目,数据访问和业务逻辑最终转移到基于C#的服务器应用程序。(数据访问已迁移)客户端位于Delphi 2010中。
我使用数据传输对象在客户机和服务器之间传递信息,但是有必要从Delphi实现我自己的更改跟踪。我最初是通过从wsdl中的DTO继承并“覆盖”getter和setter实现的。 wsdl导入中的基类(对此没有实际控制):

典型的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;
典型的吸气剂法:

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;
每当设置属性时,更改跟踪器都会将此属性名称添加到已更改属性的列表中,以返回到服务器。这使得update语句具有针对性和高效性。问题是,每个getter/setter实际上都使派生类与基类不兼容,即多态性被破坏,强制转换不再按预期工作。
上面的类是根据相应的数据库表/实体从C#中的t4模板生成的,因此更改100多个类应该不是问题。
有人对此有经验吗?
如有任何建议,将不胜感激

编辑

Wsdl导入器主要由常量组成,这些常量使用字符串格式或类似的格式来创建复杂类型的Delphi等价物。我做了以下更改,使用类似的常量名称来轻松识别我的更改,以及将它们放置在与现有代码相关的位置。 理想情况下,我会完全摆脱继承,只在wsdl中使用我的类的修改版本,因为即使我将修改后的Tdto强制转换回Dto类,我仍然无法提交修改后的Tdto,因为web服务会使用类似“expecting DtoObject,but get undtoUnit.tdtobject”的消息拒绝它。 因此,我使用继承来处理ArrayOfObjects到TList之间的转换,反之亦然。 以下是我记忆中最清楚的变化:

// 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, self.IsLoaded, 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, F%1:s, ''%1:s'', self.IsLoaded, 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'', A%2:s, F%1:s, self.IsLoaded, 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, F%1:s, ''%1:s'', self.IsLoaded, 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)],[WSDLType.LangName,
                                              Member.LangName,
                                              Member.DataType.LangName])
    else
      WriteFmt(SetterImpl3[HasIndexDecl(Member)],[WSDLType.LangName,
                                              Member.LangName,
                                              Member.DataType.LangName])

  else
    WriteFmt(SetterImpl1[HasIndexDecl(Member)],[WSDLType.LangName,
                                            Member.LangName,
                                            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' 
//在WSDLImpConst中
//我将sRemoteClassDeclPas常量值“private”更改为“protected”
//然后我在Sunitini之后添加了这些
sTrackerDec=sTrackerProcPrefix+sTrackerProcArgs+sLineBreak;
sTrackerProc=sTrackerDec+“开始”+滑动断裂+
'结果:=nProps;'+滑裂+
'如果(_加载)和(椭圆形pVal),则'+sLineBreak+
“开始”+sLineBreak+
'结果:=TrackChange(pName,nProps);'+滑裂+
'结束;'+滑裂+
'结束;'+滑裂;
sTracker2Dec=sTrackerProcPrefix+sTracker2ProcArgs+sLineBreak;
sTracker2Proc=sTracker2Dec+“开始”+滑动断裂+
'结果:=nProps;'+滑裂+
'如果(_加载)和(椭圆日期时间到椭圆日期时间(pVal)),则'+sLineBreak+
“开始”+sLineBreak+
'结果:=TrackChange(pName,nProps);'+滑裂+
'结束;'+滑裂+
'结束;'+滑裂;
sTracker3Dec=sTrackerProcPrefix+sTracker3ProcArgs+sLineBreak;
sTracker3Proc=sTracker3Dec+“开始”+sLineBreak+
'结果:=nProps;'+滑裂+
'如果nProps='',则'+sLineBreak'+
'nProps:=pName'+sLineBreak+
'else'+sLineBreak+
'nProps:=pName+'',+nProps;'+滑裂+
'结果:=nProps;'+滑裂+
'结束;'+滑裂;
sTracker4Dec=sTrackerProcPrefix+sTracker4ProcArgs+sLineBreak;
sTracker4Proc=sTracker4Dec+“开始”+sLineBreak+
'结果:=nProps;'+滑裂+
'如果(_加载)和(椭圆形pVal),则'+sLineBreak+
“开始”+sLineBreak+
'结果:=TrackChange(pName,nProps);'+滑裂+
'结束;'+滑裂+
“结束;”
//添加了我自己的setter:
sremoteclasssetterimplppas='过程%0:s.Set%1:s(常量A%2:s:%2:s);'+滑裂+
“开始”+sLineBreak+
“F%1:s:=A%2:s;”滑裂+
'结束;'+滑裂;
sRemoteClassSetterImplPas2='过程%0:s.Set%1:s(常量A%2:s:%2:s);'+滑裂+
“开始”+sLineBreak+
“F%1:s:=A%2:s;”滑裂+
“F%1:s_指定:=True;”+斯莱内布雷