I am trying to retrieve RTTI information for an instantiated Generic class using Delphi 12.2 Pro.
The Delphi documentation states:
https://docwiki.embarcadero.com/RADStudio/Athens/en/Overview_of_Generics
Run-time type identification
In Win32, generics and methods do not have run-time type information (RTTI), but instantiated types do have RTTI.
I can get RTTI information for fields and properties of instantiated Generic classes. However, I can't get RTTI for methods. Below is a sample code. Am I missing something, or is this a bug?
program Project1;
{$M+}
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Rtti;
type
TTestObject<T> = class
private
FValue: T;
function GetValue: T;
public
constructor Create(AValue: T);
property Value: T read GetValue;
end;
TIntegerObject = class(TTestObject<Integer>)
end;
{ TTestObject }
constructor TTestObject<T>.Create(AValue: T);
begin
FValue := AValue;
end;
function TTestObject<T>.GetValue: T;
begin
Result := FValue;
end;
var
t: TRttiType;
m: TRttiMethod;
o: TIntegerObject;
n: string;
begin
try
o := nil;
n := '?';
with TRttiContext.Create do
try
o := TIntegerObject.Create(10);
t := GetType(o.ClassType);
for m in t.GetMethods do
begin
if (m.name = 'GetValue') then
begin
n := m.Name;
break;
end;
end;
WriteLn('Name: ' + n); //writes "Name: ?"
ReadLn;
finally
o.free;
Free;
end;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
ReadLn;
end;
end;
end.
You are not getting RTTI information for GetValue
method because it is declared as private
and default Delphi RTTI configuration does not include private methods.
There is following declaration in System unit which is then used in RTTI compiler directive to define default RTTI configuration.
const
{ These constants represent the default settings built into the compiler.
For classes, these settings are normally inherited from TObject. }
DefaultMethodRttiVisibility = [vcPublic, vcPublished];
DefaultFieldRttiVisibility = [vcPrivate..vcPublished];
DefaultPropertyRttiVisibility = [vcPublic, vcPublished];
To change the visibility in your code, you need to use RTTI compiler directive in each unit where you want them to be different than default ones.
For instance, using following will enable RTTI for everything and you will get RTTI for GetValue
function.
{$RTTI EXPLICIT METHODS([vcPrivate..vcPublished]) PROPERTIES([vcPrivate..vcPublished]) FIELDS([vcPrivate..vcPublished])}
You can find more information about specific settings and how to use RTTI in official documentation RTTI Directive