Question

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!

Was it helpful?

Solution 2

Read c:\rad studio\9.0\source\rtl\common\System.Rtti.pas

procedure TRttiInstanceProperty.DoSetValue

The setter of the property may be

  • a field (variable)
  • a static procedure
  • a virtual procedure (your case)

And those cases make PropInfo^.SetProc have different semantics of its value. Direct address only applies to static procedures. For virtual methods you add a VMT offset and take the code address from that memory cell, as specified in that code i mentioned (but would not quote for copyright reasons).

Or you just could use TRttiProperty.SetValue and let Delphi do all those little under the hood details. See http://docwiki.embarcadero.com/Libraries/XE2/en/System.Rtti.TRttiProperty.SetValue

EDIT:

  1. the code removed - it did not worked verbatim and the topic starter provided working version.
  2. Regarding and I know I should use Extended RTTI instead of classic one - that is questionable claim. Extended RTTI is known to work noticeably slower than classic one. Dunno if someone did profiled it, but i suspect that is mostly due to the slow code of TValue. You can google and find that lot of people complained of slow TValue implementation and provided alternative ones with fixed efficiency. However since Extended RTTI only uses stock TValue it cannot benefit from those implementations and remains slower than classic one.

OTHER TIPS

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)?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top