0

我必须在我的网络服务中忽略某些东西......

数据结构:

TResIDNameRec = record
   id  : Integer;
   name: String;
end;

TResIDNameArr = array of TResIDNameRec;

TResBase = class(TJSONStructure)  // just a class(TObject)
private
public
   &type       : String;
   success     : Integer;
   errormessage: String;
   threadid    : Integer;
   constructor Create; overload;       // empty
   constructor Create(ADescendantClassName: String); overload;  // sets &type
end;

TResClass = class of TResBase;

TResGetList = class(TResBase)
private
public
   activities, 
   projects,   
   customers: TResIDNameArr;
   constructor Create; overload;    // inherited Create(Self.ClassName);
end;

然后一个

type
  TWebAct = (
   ttlogin,
   ...
   ttgetlist,
   ...
   ttgetversion
   );

const
  cWebActStructures: Array[TWebAct] of
  record
     RequestClass : TReqClass;
     ResponseClass: TResClass;
  end
  = (
     { ttlogin     } (RequestClass: TReqLogin;      ResponseClass: TResLogin;),
     ...
     { ttgetlist   } (RequestClass: TReqGetList;    ResponseClass: TResGetList;),
     ...
     { ttgetversion} (RequestClass: TReqGetVersion; ResponseClass: TResGetVersion;)
    );

我的 WebModule 上有一个私有字段:

FResponse: TResBase;     // Response object

在 WebmoduleBeforeDispatch 中,FWebAct 是一个 ttgetlist,我这样做:

lResponseClass := cWebActStructures[FWebAct].ResponseClass;
FResponse      := lResponseClass.Create(lResponseClass.ClassName);  
// FResponse.ClassName is TResGetList, OK

在处理“ttgetlist”的 TWebActionItem 的 OnAction 处理程序中,这是必不可少的部分:

var   
   lListArr : TResIDNameArr;
begin   
   lListArr := (FResponse as TResGetList).activities;

   with AClientDataSet do  
   begin
      Open;
      SetLength(lListArr,RecordCount);  // Pre-allocate (currently 152)
      l := 0;
      First;
      while not EOF do
      begin
         if SomeConditionMet then
         begin
            lListArr[l].id   := FieldByName(lIDVeld).AsInteger;
            lListArr[l].name := FieldByName(SName).AsString;
            Inc(l);
         end;
         Next;
      end;
      Close;
      SetLength(lListArr,l+1);  // Adjust (l is now 108)
    end;
    FResponse.success := 1;

lListArr 此时显示正确数据,对象检查器显示:

((3, 'Activiteit 3'), (4, 'Activiteit 3.1'), (5, 'Activiteit 3.2'), (10, 'Activiteit 3.3'), (8, 'Activiteit 5'),...

在 WebmoduleAfterDispatch 中:

var lJSO: ISuperObject;
begin
   lJSO := FResponse.ToJson;

LJSO.AsString 确实有正确的字段(&type、success、...活动、...),例如 success=1,但活动为空

{
"errormessage":"",
"success":1,
"projects":[],
"threadid":1556,
"type":"ttgetlistresult",
"customers":[],
"activities":[]
}

我在看什么?也许lListArr := (FResponse as TResGetList).activitiesOnAction 处理程序中的“不够好”?

顺便说一句,请随时更新问题标题,这是我能想到的最好的。

4

1 回答 1

3

当您分配lListArr时,局部变量会收到对该字段引用的同一数组的activities引用。但是,当您调用 时SetLength(lListArr, ...),它会lListArr引用一个数组,与之前引用的数组完全分开。

如果您希望该字段引用相同的数组,则需要将其分配回该字段:

(FResponse as TResGetList).activities := lListArr;

您可以在设置长度后随时进行该分配。更改数组的内容将通过任一变量可见。但是,更改长度与更改内容不同。更改长度会重新分配整个数组并提供一个新的唯一数组。

于 2013-08-19T15:52:32.410 回答