|
|
|||||||||||||||||||||||||||||
|
Delphi: Углубленное исследование TRTTITypeИсточник: delphi2010 Александр Божко
TRttiType обеспечивает нас удобным интерфейсом, который позволяет получать доступ ко всей информации, связанной с типом. В большинстве случаев, как мне кажется, он интуитивно понятен и документирован. Я рекомендую открыть Rtti.pas и посмотреть описание TRttiType. В общих чертах я рассказал про TRttiType в предыдущих статьях. Подобно тому, что я начал рассказывать в предыдущей статье, если ваш тип поддерживает поля, свойства и/или методы, то существуют несколько несложных методов получения доступа к ним. Такие методы предоставляют ко всем полям, свойствам и методам, имеющим RTTI информацию, и в следующих статьях я углубленно рассмотрю TRttiField, TRttiProperty и TRttiMethod. function GetMethods: TArray<TRttiMethod>; overload; virtual; function GetFields: TArray<TRttiField>; virtual; function GetProperties: TArray<TRttiProperty>; virtual; function GetMethod(const AName: string): TRttiMethod; virtual; function GetMethods(const AName: string): TArray<TRttiMethod>; overload; virtual; function GetField(const AName: string): TRttiField; virtual; function GetProperty(const AName: string): TRttiProperty; virtual; Однако, иногда вам хочется получить доступ, к тому, что было объявлено, лишь в конкретном типе и не объявлялось в родительских типах. Это можно сделать, используя следующую функциональность: function GetDeclaredMethods: TArray<TRttiMethod>; virtual; function GetDeclaredProperties: TArray<TRttiProperty>; virtual; function GetDeclaredFields: TArray<TRttiField>; virtual; Если ваш тип унаследован, вы можете получить Основной Тип с помощью вызова свойства BaseType. program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, RTTI;
type
TOneObject = Class(TObject)
end;
TTwoObject = Class(TOneObject)
end;
TThreeObject = Class(TTwoObject)
end;
var
c : TRttiContext;
t : TRttiType;
begin
c := TRttiContext.Create;
try
t := c.GetType(TThreeObject);
writeln(t.Name);
while Assigned(t.BaseType) do
begin
t := t.BaseType;
writeln(t.Name);
end;
finally
c.Free
end;
readln;
end.
Результат: TThreeObject TTwoObject TOneObject TObject Есть три набора свойств, которые дают вам больше информации о данном типе. property AsInstance: TRttiInstanceType read GetAsInstance; property IsInstance: Boolean read GetIsInstance; property AsOrdinal: TRttiOrdinalType read GetAsOrdinal; property IsOrdinal: Boolean read GetIsOrdinal; property IsSet: Boolean read GetIsSet; property AsSet: TRttiSetType read GetAsSet; Экземпляром Типов являются Классы, и тип TRttiInstanceType предоставляет свойство "MetaclassType", которое возвращает TClass для данного типа. Следующий пример показывает, как использовать этот тип для создания экземпляра объекта. program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, RTTI;
type
TOneObject = Class(TObject)
end;
TTwoObject = Class(TOneObject)
end;
TThreeObject = Class(TTwoObject)
end;
var
c : TRttiContext;
t : TRttiType;
o : TObject;
begin
c := TRttiContext.Create;
try
t := c.GetType(TThreeObject);
o := t.AsInstance.MetaclassType.Create;
Writeln(o.ClassName);
o.Free;
finally
c.Free
end;
readln;
end.
Результат TThreeObject TRttiOrdinalType ссылается на Ординальные Типы, такие как Integer, Перечисляемые типы и т.д: TOrdType = (otSByte, otUByte, otSWord, otUWord, otSLong, otULong); ... property OrdType: TOrdType read GetOrdType; property MinValue: Longint read GetMinValue; property MaxValue: Longint read GetMaxValue; Следующий пример кода демонстрирует их поведение. program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, RTTI,TypInfo;
type
TMyEnum = (enOne,enTwo,enThree);
var
c : TRttiContext;
t : TRttiType;
begin
c := TRttiContext.Create;
try
t := c.GetType(TypeInfo(TMyEnum));
writeln(GetEnumName(TypeInfo(TOrdType),ord(t.AsOrdinal.OrdType)));
writeln(t.AsOrdinal.MinValue);
writeln(t.AsOrdinal.MaxValue);
finally
c.Free
end;
readln;
end.
Результат: otUByte 0 2 Обратите внимание, я обратился к TypInfo.pas, что бы вызвать GetEnumName(), эта, и связанная с ней функция GetEnumValue() позволяет вам работать с именами перечисляемых типов, вместо ординальных значений. program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, RTTI,TypInfo;
type
TMyEnum = (enOne,enTwo,enThree);
TMySet = set of TMyEnum;
var
c : TRttiContext;
t : TRttiType;
begin
c := TRttiContext.Create;
try
t := c.GetType(TypeInfo(TMySet));
Writeln('Element Type:');
writeln(t.AsSet.ElementType.ToString);
finally
c.Free
end;
readln;
end.
Результат Element Type: TMyEnum Что бы быть последовательным, скажу, что тип TRttiRecordType наследуется от TRttiType, но он содержит всего одно новое свойство, ManagedFields, которому я не нашел осмысленного применения. property AsRecord: TRttiRecordType read GetAsRecord; property IsRecord: Boolean read GetIsRecord; Но не пропустите свойство IsRecord, оно очень полезно. program Project10;
{$APPTYPE CONSOLE}
uses
SysUtils, RTTI,TypInfo;
type
TmyRecord = record
UniStr : String;
AnsiStr : AnsiString;
WideStr : WideString;
end;
var
c : TRttiContext;
t : TRttiType;
field : TRttiField;
begin
c := TRttiContext.Create;
try
for field in c.GetType(TypeInfo(TMyRecord)).GetFields do
begin
t := field.FieldType;
writeln('Field:',field.Name);
writeln('RttiType:',t.ClassName);
if (t is TRttiStringType) then
Writeln('String Kind:',GetEnumName(TypeInfo(TRttiStringKind),ord((t as TRttiStringType).StringKind)));
Writeln;
end;
finally
c.Free
end;
readln;
end.
Результат: Field:UniStr RttiType:TRttiStringType String Kind:skUnicodeString Field:AnsiStr RttiType:TRttiAnsiStringType String Kind:skAnsiString Field:WideStr RttiType:TRttiStringType String Kind:skWideString В заключение замечу, что существуют несколько других не очень значимых свойств TRttiType, но я не пытаюсь переписывать документацию, поэтому я оставлю их для самостоятельного исследования. Ссылки по теме
|
|
|||||||