No runtime type information on interface properties

You might have tried to decorate an interface property in Delphi with a custom attribute like in this question on StackOverflow.

Unfortunately, that won’t work, as I explained in my answer. No runtime type information is generated for interface properties so your attribute will have no effect, even though there’s no compiler warning. You can try the code below which demonstrates it.

Of course, if you can prove me wrong or have another idea please let me know in a comment here. Thanks!

Here’s the code:


program Test;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,
System.Rtti;

type
TTestAttribute = class(TCustomAttribute)
private
FName: string;
public
constructor Create(const AName: string);
property Name: string read FName;
end;

[TTestAttribute('AtInterface')]
ITestInterface = interface(IInvokable)
['{92A8107E-B40E-4786-A02E-251EA0DB3937}']
[TTestAttribute('AtMethod')]
function GetValue: string;
[TTestAttribute('AtMethod')]
procedure SetValue(const AValue: string);
[TTestAttribute('AtProperty')]
property Value: string read GetValue write SetValue;
end;

constructor TTestAttribute.Create(const AName: string);
begin
inherited Create;
FName := AName;
end;

procedure ShowAttributes(const Attributes: TArray<TCustomAttribute>);
var
Attr: TCustomAttribute;
begin
for Attr in Attributes do
if Attr is TTestAttribute then
Writeln(Format('%s(''%s'')', [Attr.ClassName, TTestAttribute(Attr).Name]))
else
Writeln(Attr.ClassName);
end;

procedure Main;
var
Ctx: TRttiContext;
AType: TRttiInterfaceType;
Attributes: TArray<TCustomAttribute>;
Method: TRttiMethod;
Prop: TRttiProperty;
begin
Ctx := TRttiContext.Create;
AType := Ctx.GetType(TypeInfo(ITestInterface)) as TRttiInterfaceType;
Writeln(Format('Attributes on the interface ''%s'':', [AType.Name]));
ShowAttributes(AType.GetAttributes);
Writeln;
for Method in AType.GetMethods do
begin
Writeln(Format('Attributes on method ''%s'':', [Method.Name]));
ShowAttributes(Method.GetAttributes);
end;
Writeln;
for Prop in AType.GetProperties do
begin
Writeln(Format('Attributes on property ''%s'':', [Prop.Name]));
ShowAttributes(Prop.GetAttributes);
end;
end;

begin
try
Main;
Readln;
except
on E: Exception do
begin
ExitCode := 1;
Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
end;
end;
end.

This produces the following output:

Attributes on the interface:
TTestAttribute('AtInterface')

Attributes on method 'GetValue':
TTestAttribute('AtMethod')
Attributes on method 'SetValue':
TTestAttribute('AtMethod')

Already the call to AType.GetProperties returns an empty array; there is no RTTI for interface properties.

Leave a Reply

Your email address will not be published. Required fields are marked *