Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi - Extract setter method's name of a property

In the following type:

MyClass = class(TInterfacedPersistent)
private
  FMyProperty: Integer;      
published
  procedure setMyProperty(Value: Integer); virtual;
  property MyProperty: Integer read FMyProperty write setMyProperty;

I would like to know the name of the setter method of the "MyProperty" property via RTTI. I've tried the following:

    procedure ShowSetterMethodsNames(pMyObject: TObject);
    var
      vPropList: TPropList;      
      vCount, I: Integer;
    begin
      vCount:= GetPropList(pMyObject.ClassInfo, tkProperties, @vPropList);

      for I:= 0 to vCount -1 do
      begin
          if Assigned(vPropList[I]^.SetProc) then
            ShowMessage(pMyObject.ClassType.MethodName(vPropList[I]^.SetProc));
      end;
    end;

Although the pointer is not nil, all I have is an empty message. Does anybody have some tip to me?

P.S.: I'm using Delphi XE4, and I know I should use extended RTTI instead of classic, but anyway, I can't do what I want in both features... So, any help will be appreciated. Thanks for the replies.


FINAL EDITION, problem solved:

Here is the code working, based in the (help of my friends and...) RTTI unit (DoSetValue method of TRTTIInstanceProperty class):

procedure ShowVirtualSettersNames(pObject: Pointer);
var
  vSetter, vPointer: Pointer;
  vPropList: TArray<TRttiProperty>;
  vProp: TRttiProperty;
begin
  vPropList:= RTTIUtils.ExtractProperties(TObject(pObject).ClassType); // Helper to get properties from a type, based in extended RTTI

  for vProp in vPropList do
  begin
    vPointer:= TRttiInstanceProperty(vProp).PropInfo^.SetProc;
    vPointer:= PPointer(PInteger(pObject)^ + Smallint(vPointer))^;    
    ShowMessage(TObject(pObject).ClassType.MethodName(vPointer));
  end;
end;

This ONLY WORKS FOR VIRTUAL SETTERS, for statics the message is empty. Thanks everyone!

like image 285
Daniel Chaves Avatar asked Jul 17 '13 02:07

Daniel Chaves


1 Answers

You can retrieve this method name, if

a) move the method to the published section (classic RTTI works with this section only (more accurately - compiled with {$M+} directive))

b) use right class specifier - MyClass.MethodName, because MethodName is class function

This code works on D7 and XE3:

MyClass = class(TInterfacedPersistent)
private
  FMyProperty: Integer;
published
   procedure setMyProperty(Value: Integer);
   property MyProperty: Integer read FMyProperty write setMyProperty;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  ppi: PPropInfo;
begin
  ppi := GetPropInfo(MyClass, 'MyProperty');
  ShowMessage(MyClass.MethodName(ppi.SetProc));
end;

P.S. What Delphi version are you using? What about Extended RTTI (since D2010)?

like image 198
MBo Avatar answered Nov 15 '22 07:11

MBo