Как получить ссылку на объект или его данные из визуализатора отладчика внешнего средства просмотра? - PullRequest
4 голосов
/ 13 ноября 2011

Я пытаюсь написать визуализатор отладчика для TJSONObject или TJSONValue. У меня большая часть визуализатора работает хорошо. У меня проблема с получением ссылки на TJSONObject или, по крайней мере, на значение tostring () TJSONObject.

В соответствии с примерами, которые я видел, а также с хорошим постом Джереми Норта в http://edn.embarcadero.com/article/40268, я должен получить то, что мне нужно, от метода Show моей реализации IOTADebuggerVisualizerExternalViewer. В частности, из строковых параметров Expression, TypeName и EvalResult.

Из того, что я понимаю, Expression - это имя проверяемой (визуализируемой) переменной, TypeName - имя класса переменной, а EvalResult - строковое представление переменной по умолчанию.

Для простого теста я поместил TMemo на моего потомка TFrame. Из метода IOTADebuggerVisualizerExternalViewer.Show я вызываю метод ShowJSONObject моего TFrame, которому я передаю 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

Результат выглядит так:

A debugger visualizer under development

Я надеялся, что EvalResult вернет представление tostring объекта TJSONObject, но он вернул только uninforrative (), то же самое вы видите по умолчанию в окне локальных переменных.

Как получить представление tostring объекта TJSONObject, для которого был вызван визуализатор, или дескриптор фактического объекта, чтобы я мог деконструировать и отобразить его значение?

1 Ответ

3 голосов
/ 14 ноября 2011

Вам нужно оценить свое выражение (включая вызов 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'));
...