Call the protected method (constructor) via RTTI

am using XE-2.

Is it possible to call a protected method (constructor) using RTTI?

I searched the Internet but could not find a definitive answer. I understand that before XE, only published methods / properties were available. I have write access to private fields, so I expected that I could use protected methods.

The following code works as long as the constructor is open.

function GetDefaultConstructor(aRttiType: TRttiType): TRttiMethod;
var
   Method: TRttiMethod;
begin
   for Method in aRttiType.GetMethods('Create') do
   begin
      if (Method.IsConstructor) and (length(Method.GetParameters) = 0) and (Method.Parent = aRttiType) then
         Exit(Method);
   end;
   Result := nil;
end;
+4
source share
3 answers

RTTI information increases the size of executable files. Because of this, designers provided the developer with the ability to specify which RTTI information should be associated with the executable.

, RTTI . , RTTI. ,

{$APPTYPE CONSOLE}

uses
  System.TypInfo, System.Rtti;

type
  TMyClass = class
  protected
    constructor Create;
  end;

constructor TMyClass.Create;
begin
end;

var
  ctx: TRttiContext;
  method: TRttiMethod;

begin
  for method in ctx.GetType(TMyClass).GetMethods do
    if method.Visibility=mvProtected then
      Writeln(method.Name);
end.

.

{$APPTYPE CONSOLE}

uses
  System.TypInfo, System.Rtti;

type
  {$RTTI EXPLICIT METHODS([vcProtected])}
  TMyClass = class
  protected
    constructor Create;
  end;

constructor TMyClass.Create;
begin
end;

var
  ctx: TRttiContext;
  method: TRttiMethod;

begin
  for method in ctx.GetType(TMyClass).GetMethods do
    if method.Visibility=mvProtected then
      Writeln(method.Name);
end.

Create

. :

+8

RTTI . RTTI EXPLICIT , RTTI- , .

  {$RTTI EXPLICIT METHODS([vcPrivate, vcProtected, vcPublic, vcPublished])}
  TFoo= class
  protected
    constructor Create;
  end;
+10

RTTI, , protected , , .

Delphi : , protected , . , , . , , , .

, . , .

, DestroyWindowHandle VCL TWinControl - . , TWinControl, . , , - HWND , :

type
  TWinControlEx = class(TWinControl);


procedure TMyForm.MyButtonClick(Sender: TObject);
begin
  TWinControlEx(Sender).DestroyWindowHandle;  // button window is destroyed but the button itself remains!
end;

, , , ?

, . , , , :

unit Unit2;

interface

   type
     TFoo = class
     protected
       constructor Create;
     end;

implementation

  constructor TFoo.Create;
  begin
    inherited Create;

    // Foo specific, protected initialisation here....
  end;

end.

- ...

unit Unit1;

  ..

implementation

  uses
    Unit2;

  type
    TFooEx = class(TFoo);


  procedure TMyForm.FormCreate(Sender: TObject);
  var
    foo: TFoo;
  begin
    foo := TFooEx.Create;  // << the protected constructor!
  end;    

, foo TFooEx, TFoo. . , , , :

if foo is TFoo then

- , . , :

if foo.ClassType = TFoo then

( foo.ClassType = TFooEx, TFoo).

, , protected, , , , . , , , , () TFoo, , , :

// unit2

     TFoo = class
     protected
       constructor Create; virtual;
     end;

     TBar = class(TFoo)
     protected
       constructor Create; override;
     end;

...

TFooEx = class(TBar);


procedure ....;
var
  foo: TFoo;
begin
  foo := TFooEx.Create;  // << creates a TBar using protected TBar constructor
end;

< >

RTTI , , RTTI .

Another advantage is that if the signatures of the protected methods that you call in this way are changed, then the code simply does not compile, and not only does not work at run time. It also means that you get help from code completion and understanding when making a constructor call, reducing the likelihood of errors in the number or type of parameters.

+4
source

All Articles