9

Is there a way to explore a interface's properties with Rtti?

The following code does not work:

procedure ExploreProps;
var
  Ctx: TRttiContext;
  RttiType: TRttiType;
  RttiProp: TRttiProp;
begin
  RttiType := Ctx.GetType(TypeInfo(IMyInterface));
  for RttiProp in RttiType.GetProperties do
    Writeln(RttiProp.ToString);
end;

Has anyone a solution how to do this correctly?

Christian Metzler
  • 2,971
  • 5
  • 24
  • 30

4 Answers4

5

Interfaces are collections of functions. They don't really have properties the way objects do; that's just a bit of syntactic sugar that the compiler adds for you to make it easier to write code for them. The difference is that on objects, properties allow controlled access to private and protected members, whereas on interfaces, all members are public so there's no need for the properties.

Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • Ok, but exploring a interfaces methods doesn't work either... Just replaced the for loop by using RttiType.GetMethods, still no results. – Christian Metzler Sep 12 '10 at 15:21
  • 4
    @Christian: I just looked at the code for the RTTI system, and a lot of interfaces in the standard libraries are set up with no RTTI generated for them. I'm not sure what the rules are for generating extended RTTI for interface types, since it seems to be different from generating extended RTTI for classes or records. Maybe Barry Kelly or Allen Bauer could answer this one? – Mason Wheeler Sep 12 '10 at 15:37
  • An interface type needs to have `{M+}` applied to it in order for `TRttiType.GetMethods()` to report the interface's methods. – Remy Lebeau Apr 16 '15 at 20:59
1

Add this function in your interface

function GetObject: TObject;

and implement it in the class. the use the GetObject function with RTTI routines

var
  obj: IPerson;
begin
  obj := TPerson.Create;
  Count := GetPropList(obj.GetObject.ClassInfo, tkAny, @List);
end;

Please note that your class should be inherited from TInterfacedPersistent not TInterfacedObject

TPerson = class(TInterfacedPersistent, IPerson)
FLICKER
  • 6,439
  • 4
  • 45
  • 75
1

As I known, there is no support for normal interfaces. You could add {$M+} and then try again.

Baoquan Zuo
  • 652
  • 4
  • 15
-1

late answer, but you could typecast your interfae to TObject, e.g.

RttiType := Ctx.GetType(TObject(IMyInterface).ClassInfo);
webcss
  • 7
  • 1
  • That is incorrect and dangerous. Due to memory layout interfaces can not be cast back to objects. You would have to add a function to the interface to get back to the object (like in @FLICKERs answer). – Jens Mühlenhoff May 07 '17 at 12:04