Доступ к строгому приватному полю с использованием RTTI - PullRequest
6 голосов
/ 23 сентября 2011

рассмотрите этот простой код

{$APPTYPE CONSOLE}

uses
  Rtti,
  SysUtils;

type
  {$M+}
  TFoo = class
  strict private
    class var Field1 : Integer;
    field2 :  Integer;
  private
    field3 :  Integer;
    class var Field4 : Integer;
  end;


Var
    ctx : TRttiContext;
    f   : TRttiField;
begin
  try
    ctx:=TRttiContext.Create;

    for f in ctx.GetType(TFoo).GetFields do
     Writeln(f.Name);


    Writeln('Done');
    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Когда вы запускаете это, в списке отображается только field3. кажется, что RTTI не поддерживает поля, которые strict private или class var, поэтому вопросы Is possible access a strict private field of a delphi class using Rtti or another method?, и я прочитал документацию по методу RTTI.TRttiType.GetFields , но упоминает эти ограничения Exist any paper or article which mentions such limitations?

Ответы [ 3 ]

6 голосов
/ 23 сентября 2011

Я не могу попробовать прямо сейчас, но вам может показаться, что вам нужно GetDeclaredFields вместо GetFields.Это должно дать все (экземпляр) поля класса, но не поля предшественника.Если они вам тоже нужны, вам придется рекурсивно пройтись по цепочке наследования.

Как я уже сказал, я не могу попробовать это прямо сейчас, поэтому вам придется убедиться в этом самим, даст ли это вамдоступ к строгим закрытым полям.

Обновление

Обратите внимание, что в вашем объявлении TFoo , даже вы, вероятно, не предполагали, и Field1, иField2 - это переменные класса! .

Просто переформатируйте объявление, и вы поймете, что я имею в виду:

  TFoo = class
  strict private
    class var
      Field1: Integer;
      Field2: Integer;
  private
    // etc...

Все, что идет после class var является переменной класса, пока компилятор не встретит var , строгий , закрытый , защищенный и т. д. Попробуйте, и вытакже см. Field2 записывается:

  TFoo = class
  strict private
    class var 
      Field1: Integer;
    var 
      Field2: Integer;
    // etc...

В качестве альтернативы попробуйте:

  TFoo = class
  strict private
    Field2: Integer;
    class var 
      Field1: Integer;
    // etc...

Это означает, что GetFields и GetDeclaredFields не имеют никаких проблем со строгимчастные поля .Они просто не возвращают переменные класса.Это имеет смысл, ИМО.Переменные класса не являются членами исследуемого объекта.

3 голосов
/ 19 декабря 2011

Доступ к строгим закрытым членам класса возможен с Class Helpers.

См. Доступ к строгой защищенной собственности-del -i-класс для рабочего примера.

Связано также как можно получить доступ к значению класса, используя переменную адресации класса-and-a-offset-to-the-variable , где помощники классов используются для доступа к строгому закрытому классу var.

2 голосов
/ 23 сентября 2011

По определению, strict private виден только в области действия самого класса. Тем не менее, они должны быть доступны с Халвордским хаком # 5 (за исключением полей класса, я думаю).

...