Information for Simple Types
Go Up to Working with RTTI
Contents
Introduction
In Delphi, there are two basic categories of types: simple and structured. In terms of type information, simple types usually carry far less information than structured types.
To verify whether the obtained TRttiType reflects a given type, use the TRttiType.TypeKind property. Its value specifies the actual type kind. The other method is to use the is
operator to detect the actual class type for a TRttiType instance:
{ Display only the string types }
for LType in LContext.GetTypes() do
if LType is TRttiStringType then
Writeln(LType.ToString);
// Display only the string types
DynamicArray<TRttiType*>typeArray = context->GetTypes();
for (int i = 0; i < typeArray.Length; i++) {
TRttiType *type = typeArray[i];
TRttiStringType *stringType = dynamic_cast<TRttiStringType*>(type);
if (stringType) {
printf("%ls\n", stringType->ToString().c_str());
}
}
The previous example displays only the string types declared in the application and its packages.
Ordinal Types
Ordinal types are described by TRttiOrdinalType class instances. TRttiOrdinalType exposes properties used to access the information specific to ordinal types such as MinValue, MaxValue, and OrdType.
The following example enumerates all ordinal types defined in the application or its packages and prints their properties on the console:
for LType in LContext.GetTypes() do
if LType is TRttiOrdinalType then
begin
Writeln('Type name:', LType.Name);
Writeln('Min allowed value:', TRttiOrdinalType(LType).MinValue);
Writeln('Max allowed value:', TRttiOrdinalType(LType).MaxValue);
Writeln;
end;
// Enumerate all types declared in the application
DynamicArray<TRttiType*>typeArray = context->GetTypes();
for (int i = 0; i < typeArray.Length; i++) {
TRttiType *type = typeArray[i];
TRttiOrdinalType *ordinalType = dynamic_cast<TRttiOrdinalType*>(type);
if (ordinalType) {
printf("%ls\n", ordinalType->ToString().c_str());
printf("\t min value: %ld\n", ordinalType->MinValue);
printf("\t max value: %ld\n", ordinalType->MaxValue);
}
}
Note that enumeration types are also considered ordinal, so the previous example will also print the information they contain.
64-bit Integer Types
64-bit integers do not share the same base type as the ordinal types. Because of this, 64-bit integers are described by the TRttiInt64Type class. TRttiInt64Type exposes the MinValue and MaxValue properties, similarly to TRttiOrdinalType.
The following example enumerates all 64-bit integers declared in the application or its packages:
for LType in LContext.GetTypes() do
if LType is TRttiInt64Type then
begin
Writeln('Type name:', LType.Name);
Writeln('Min allowed value:', TRttiInt64Type(LType).MinValue);
Writeln('Max allowed value:', TRttiInt64Type(LType).MaxValue);
Writeln;
end;
DynamicArray<TRttiType*>typeArray = context->GetTypes();
for (int i = 0; i < typeArray.Length; i++) {
TRttiType *type = typeArray[i];
TRttiInt64Type *int64Type = dynamic_cast<TRttiInt64Type*>(type);
if (int64Type) {
printf("type name: %ls\n", int64Type->ToString().c_str());
printf("\t min allowed value: %Ld\n", int64Type->MinValue);
printf("\t max allowed value: %Ld\n", int64Type->MaxValue);
}
}
Floating-Point Types
Floating-point types are described by TRttiFloatType class instances. TRttiFloatType exposes only one property, called FloatType, which allows identifying the floating-point subtype.
The following example prints all the declared floating-point types whose subtype is Double:
for LType in LContext.GetTypes() do
if (LType is TRttiFloatType) and (TRttiFloatType(LType).FloatType = ftDouble) then
Writeln('Type name:', LType.Name);
The printed results include the Double type itself, the Real type, which is a double type and date-time types declared in the System unit.
Set Types
Set types are described by TRttiSetType class instances. The only property exposed by TRttiSetType is ElementType, which provides type information for the elements that make up the set. For example, given a set defined as:
type
TByteSet = set of Byte;
the following code prints the type name of the set of elements (which is Byte):
var
LContext: TRttiContext;
LType: TRttiSetType;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Obtain the TRttiSetType for our type }
LType := LContext.GetType(TypeInfo(TByteSet)) as TRttiSetType;
{ Print the type name of the set elements }
Writeln('The elements of the set are of ', LType.ElementType.Name, ' type.');
end.
Enumeration Types
Enumeration types are described by TRttiEnumerationType class instances. TRttiEnumerationType is derived from TRttiOrdinalType and adds up a new property, called UnderlyingType. UnderlyingType provides type information for the actual enumeration type that is used in this enumeration type.
Consider two enumeration types, one new and the other one being an alias of the standard TSeekOrigin enumeration:
type
TNewEnum = (neOne, neTwo, neThree);
TOtherEnum = type TSeekOrigin;
The following code prints the name of the underlying type for both types:
{ Obtain the type information for both types }
LType1 := LContext.GetType(TypeInfo(TNewEnum)) as TRttiEnumerationType;
LType2 := LContext.GetType(TypeInfo(TOtherEnum)) as TRttiEnumerationType;
{ Print the type names for the underlying types }
Writeln('Underlying type for TNewEnum is ', LType1.UnderlyingType.Name);
Writeln('Underlying type for TOtherEnum is ', LType2.UnderlyingType.Name);
You should note that, for newly declared enumeration types (for example, TNewEnum), the UnderlyingType property returns the type information for the enumeration type itself. For strong aliased types (such as TOtherEnum), UnderlyingType returns the type information of that type.
Strings
String types are described by TRttiStringType class instances. TRttiStringType exposes only one property, called StringKind, which allows identifying the actual string type. The string type can be:
- Short string
- Ansi string
- Wide string
- Unicode string
The following example prints all ANSI string types declared in the application or its packages:
for LType in LContext.GetTypes() do
if (LType is TRttiStringType) and (TRttiStringType(LType).StringKind = skAnsiString) then
Writeln(LType.Name);
For AnsiString types, the Rtti unit defines a special TRttiAnsiStringType class. TRttiAnsiStringType is derived from TRttiStringType and it adds a new CodePage property, which can be used to obtain the code page of the AnsiString.
The following example prints the code page of the RawByteString type:
{ Obtain type information for RawByteString (which is an AnsiString) }
LType := LContext.GetType(TypeInfo(RawByteString)) as TRttiAnsiStringType;
Writeln('The codepage of the string is ', LType.CodePage);
Class References (Metaclasses)
Class reference types are described by TRttiClassRefType class instances. TRttiClassRefType allows obtaining the class type that is used for the base of the hierarchy denoted by the metaclass (using the InstanceType property). TRttiClassRefType also provides direct access to the metaclass itself, through MetaclassType.
The following example prints all the metaclass types declared in the application or its packages; they represent types that are derived from TComponent:
var
LContext: TRttiContext;
LType: TRttiType;
LMeta: TRttiClassRefType;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
{ Get all types that are class references and whose class inherits from TComponent }
for LType in LContext.GetTypes() do
if (LType is TRttiClassRefType) then
begin
{ Typecast the Rtti type class }
LMeta := TRttiClassRefType(LType);
if (LMeta.MetaclassType.InheritsFrom(TComponent)) then
begin
Writeln('The metaclass type name is ', LType.Name);
Writeln('The hierarchy starts at ', LMeta.InstanceType.Name);
end;
end;
end.
To better understand the information listed by the previous example, consider this type definition:
type
TButtonClass = class of TButton;
For this type, the MetaclassType property returns the metaclass itself, while the InstanceType property returns the type information of the TButton class. TButton, in this case, starts the metaclass hierarchy.
Method and Procedural Types
Method types are described by TRttiMethodType class instances, while procedural types are described by TRttiProcedureType instances. Neither TRttiMethodType, nor TRttiMethodType provides additional information and should be used only to detect the types:
{ Find and print all event types declared in the application }
for LType in LContext.GetTypes() do
if (LType is TRttiMethodType) and EndsStr('Event', LType.Name) then
Writeln(LType.Name);
Pointers
In Delphi, pointer types also have RTTI information emitted for them. They are represented by TRttiPointerType class instances. TRttiPointerType exposes a single property, ReferredType, which provides type information for the pointed type.
For example, given the following type:
type
TStrPtr = ^String;
the ReferredType property provides type information for the String type that is being pointed to by the pointer type. The following code demonstrates how you can obtain this information:
var
LContext: TRttiContext;
LType: TRttiPointerType;
begin
{ Obtain the RTTI context }
LContext := TRttiContext.Create;
LType := LContext.GetType(TypeInfo(TStrPtr)) as TRttiPointerType;
Writeln(LType.ReferredType.Name);
end.
Note that for untyped pointer types (such as Pointer), ReferredType is nil, because it does not point to any specific type.