5

我正在尝试为 TJSONObject 或 TJSONValue 编写调试器可视化工具。我的大部分可视化工具都工作得很好。我遇到的问题是获取对 TJSONObject 的引用,或者至少是对 TJSONObject 的 tostring() 值的引用。

根据我看到的示例,以及 Jeremy North 在http://edn.embarcadero.com/article/40268上的精彩帖子,我应该从 IOTADebuggerVisualizerExternalViewer 实现的 Show 方法中得到我需要的东西。具体来说,来自 Expression、TypeName 和 EvalResult 字符串参数。

据我了解,Expression 是被检查(可视化)的变量的名称,TypeName 是变量的类名,而 EvalResult 是变量的默认字符串表示形式。

对于一个简单的测试,我在我的 TFrame 后代上放置了一个 TMemo。从 IOTADebuggerVisualizerExternalViewer.Show 方法中,我调用了 TFrame 的 ShowJSONObject 方法,并将 Expression、TypeName 和 EvalResult 传递给该方法。相关代码出现在这里:

function TDebuggerJSONVisualizer.Show(const Expression, TypeName, EvalResult: string;
  SuggestedLeft, SuggestedTop: Integer): 
  IOTADebuggerVisualizerExternalViewerUpdater;
var
  AForm: TCustomForm;
  AFrame: TJSONViewerFrame;
  VisDockForm: INTACustomDockableForm;
begin
  VisDockForm := TJSONVisualizerForm.Create(Expression) as INTACustomDockableForm;
  AForm := (BorlandIDEServices as INTAServices).CreateDockableForm(VisDockForm);
  AForm.Left := SuggestedLeft;
  AForm.Top := SuggestedTop;
  (VisDockForm as IFrameFormHelper).SetForm(AForm);
  AFrame := (VisDockForm as IFrameFormHelper).GetFrame as TJSONViewerFrame;
  AFrame.ShowJSONObject(Expression, TypeName, EvalResult);
  Result := AFrame as IOTADebuggerVisualizerExternalViewerUpdater;
end;

{ TStringListViewerFrame }

procedure TJSONViewerFrame.ShowJSONObject(const Expression, TypeName,
  EvalResult: string);
begin
  Memo1.Lines.Add(Expression);
  Memo1.Lines.Add(TypeName);
  Memo1.Lines.Add(EvalResult);
end;

如您所见,此时我只是尝试从 ShowJSONObject 方法中显示这三个参数的值。

这是我尝试使用可视化工具显示的简单 TJSONObject:

var
 jo: TJSONObject;
begin
  jo := TJSONObject.Create;
  jo.AddPair('one', 'one');
  jo.AddPair('two', TJSONNumber.Create(1)); //a breakpoint here

结果如下所示:

正在开发的调试器可视化工具

我希望 EvalResult 会返回 TJSONObject 的 tostring 表示,但它只返回无信息的 (),这与您在局部变量窗口中默认看到的内容相同。

如何获取为其调用可视化工具的 TJSONObject 的 tostring 表示或实际对象的句柄,以便我可以解构并显示其值?

4

1 回答 1

3

您需要使用此过程评估您的表达式(包括 ToString 调用)(刚刚从我自己的可视化器源中复制,因此它可以使用一些未在此处声明的局部变量):

function TJSONViewerFrame.Evaluate(Expression: string): string;
var
  CurProcess: IOTAProcess;
  CurThread: IOTAThread;
  ResultStr: array[0..4095] of Char;
  CanModify: Boolean;
  ResultAddr, ResultSize, ResultVal: LongWord;
  EvalRes: TOTAEvaluateResult;
  DebugSvcs: IOTADebuggerServices;
begin
  begin
    Result := '';
    if Supports(BorlandIDEServices, IOTADebuggerServices, DebugSvcs) then
      CurProcess := DebugSvcs.CurrentProcess;
    if CurProcess <> nil then
    begin
      CurThread := CurProcess.CurrentThread;
      if CurThread <> nil then
      begin
        EvalRes := CurThread.Evaluate(Expression, @ResultStr, Length(ResultStr),
          CanModify, eseAll, '', ResultAddr, ResultSize, ResultVal, '', 0);
        case EvalRes of
          erOK: Result := ResultStr;
          erDeferred:
            begin
              FCompleted := False;
              FDeferredResult := '';
              FDeferredError := False;
              FNotifierIndex := CurThread.AddNotifier(Self);
              while not FCompleted do
                DebugSvcs.ProcessDebugEvents;
              CurThread.RemoveNotifier(FNotifierIndex);
              FNotifierIndex := -1;
              if not FDeferredError then
              begin
                if FDeferredResult <> '' then
                  Result := FDeferredResult
                else
                  Result := ResultStr;
              end;
            end;
          erBusy:
            begin
              DebugSvcs.ProcessDebugEvents;
              Result := Evaluate(Expression);
            end;
        end;
      end;
    end;
  end;
end;

所以现在你可以用这样的东西替换你的 Show 函数:

AFrame.ShowJSONObject(Expression, TypeName, Evaluate(Expression + '.ToString'));
于 2011-11-14T17:03:48.753 回答