Некоторые типы, такие как классы и записи, содержат "элементы (members)", такие как поля, свойства и методы. RTTI информация начинается с TRttiMember , который предоставляет 4 бита информации о каждом Элементе.
- Имя;
- Область видимости (private, protected, public, published);
- Тип, с которым ассоциируется элемент;
- Атрибуты, ассоциирующиеся с этим элементом.
Этот пример кода демонстрирует, как получить доступ к каждому из них.
program Project4;
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti, TypInfo;
type
TTest = class(TCustomAttribute)
end;
TBook = class(TObject)
private
FTitle: String;
public
[TTest]
property Title : String read FTitle write FTitle;
end;
var
c : TRttiContext;
m : TRttiMember;
{ TExample }
begin
c := TRttiContext.Create;
m := c.GetType(TBook).GetProperty('Title');
Writeln('Name:',m.Name);
Writeln('Visibility:',GetEnumName(TypeInfo(TMemberVisibility),ord(m.Visibility)));
WriteLn('Parent:',m.Parent.ToString);
Writeln('First Attribute:',m.GetAttributes[0].ToString);
writeln;
m := c.GetType(TBook).GetField('FTitle');
WriteLn('Name:',m.Name);
WriteLn('Visibility:',GetEnumName(TypeInfo(TMemberVisibility),ord(m.Visibility)));
WriteLn('Parent:',m.Parent.ToString);
readln;
c.Free;
end.
Результат:
Name:Title
Visibility:mvPublic
Parent:TBook
First Attribute:TTest
Name:FTitle
Visibility:mvPrivate
Parent:TBook
Два основных наследника TRttiMember, о которых я хочу рассказать в этом посте, - TRttiField и TRttiPropery. Оба они позволяют вам получить и получать и присваивать значения экземпляров данного типа. Соответственно, они оба имеют методы SetValue() и GetValue().
Следующий код демонстрирует, как их использовать. Если вы пропустили мое Введение в TValue, то я советую вам уделить некоторое время, что прочесть его, так как это позволит объяснить то "волшебство", которое будет дальше.
program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti, TypInfo;
type
TBook = class(TObject)
private
FTitle: String;
public
property Title : String read FTitle write FTitle;
end;
var
c : TRttiContext;
p : TRttiProperty;
f : TRttiField;
book : TBook;
v : TValue;
begin
book := TBook.Create;
try
c := TRttiContext.Create;
p := c.GetType(TBook).GetProperty('Title');
p.SetValue(Book,'Go, Dog, Go!');
v := p.GetValue(Book);
Writeln('Title:',v.ToString);
f := c.GetType(TBook).GetField('FTitle');
f.SetValue(Book,'Green Eggs and Ham');
v := f.GetValue(Book);
Writeln('FTitle:',v.ToString);
readln;
c.Free;
finally
Book.Free;
end;
end.
Результат:
Title:Go, Dog, Go!
FTitle:Green Eggs and Ham
Говоря о свойствах (Properties), вы должны проследить за тем, допускают -ли они возможность считывания и записи значения, так как попытка вызова SetValue для не изменяемого свойства вызовет исключение EPropReadOnly. TRttiProperty имеет два свойства "isReadable" и 'isWritable", которые позволяют вам определить, каким образом свойство было описано. Следующий код демонстрирует, как это работает.
program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, Rtti, TypInfo;
type
TBook = class(TObject)
private
FTitle: String;
FUgly: String;
FAuthor: String;
public
property Title : String read FTitle write FTitle;
property Author : String read FAuthor;
property Ugly : String write FUgly;
end;
var
c : TRttiContext;
p : TRttiProperty;
begin
c := TRttiContext.Create;
try
p := c.GetType(TBook).GetProperty('Title');
WriteLn('Name:',p.Name);
Writeln('IsReadable:',p.IsReadable);
Writeln('IsWritable:',p.IsWritable);
writeln;
p := c.GetType(TBook).GetProperty('Author');
WriteLn('Name:',p.Name);
Writeln('IsReadable:',p.IsReadable);
Writeln('IsWritable:',p.IsWritable);
writeln;
p := c.GetType(TBook).GetProperty('Ugly');
WriteLn('Name:',p.Name);
Writeln('IsReadable:',p.IsReadable);
Writeln('IsWritable:',p.IsWritable);
readln;
finally
c.Free;
end;
end.
Результат:
Name:Title
IsReadable:TRUE
IsWritable:TRUE
Name:Author
IsReadable:TRUE
IsWritable:FALSE
Name:Ugly
IsReadable:FALSE
IsWritable:TRUE
Этот пост в значительной мере приоткрыл завесу над TRttiField и TRttiProperty, в следующем посте я расскажу о TRttiMethod.
Ссылки по теме