(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

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, Перечисляемые типы и т.д:
Он содержит 3 новых свойства, для того, что бы помочь вам при работе с ординальными типами.

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() позволяет вам работать с именами перечисляемых типов, вместо ординальных значений.
RTTI информация, которая была доступна в предыдущих версиях Delphi для получения информации о типе, использовала указатель, т.е. "pTypeInfo".
Теперь это хранится в свойстве .Handle TRttiType, я рассказываю об этом, как и о процедурах модуля TypInfo.pas , на тот случай, если вам понадобится обратиться к низкоуровневой функциональности.
TRttiSetType предоставляет одно новое свойство "ElementType", которое позволяет вам получать тип элементов множества. Следующий код демонстрирует это в действии.

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, оно очень полезно.
Существуют и несколько других наследников, которые позволят вам использовать стандартные "is" и "as" для получения доступа к дополнительной информации, связанной с данным типом.
TRttiInterfaceType
TRttiInt64Type
TRttiMethodType
TRttiClassRefType
TRttiEnumerationType
TRttiStringType
TRttiAnsiStringType
TRttiFloatType
TRttiArrayType
TRttiDynamicArrayType
TRttiPointerType
TrttiProcedureType
Следующий код показывает, как вы можете преобразовать тип TRttiType в TRttiStringType, для того, что бы выяснить с каким строковым типом вы имеете дело.

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, но я не пытаюсь переписывать документацию, поэтому я оставлю их для самостоятельного исследования.

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 22.10.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Delphi Professional Named User
Enterprise Connectors (1 Year term)
IBM Domino Messaging Client Access License Authorized User License + SW Subscription & Support 12 Months
Microsoft 365 Apps for business (corporate)
TeeBI for RAD Studio Suite with source code single license
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Windows и Office: новости и советы
Corel DRAW - от идеи до реализации
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100