RTTI (2) obtain type information [from monopoly]

Source: Internet
Author: User
Part 2

Obtain the type information of a method.

Obtains the RTTI information of the ordinal and set types.

 

⊙ Obtain method type information

The so-called method is a function pointer declared with the of object keyword. The following function can display the type information of a method:

Procedure GetMethodTypeInfo (ATypeInfo: PTypeInfo; AStrings: TStrings); type PParamData = ^ TParamData; TParamData = record // data structure of function parameters Flags: TParamFlags; // parameter passing rule ParamName: required string; // parameter name TypeName: Required string; // parameter type name end; function GetParamFlagsName (AParamFlags: TParamFlags): string; var I: Integer; begin Result: = ''; for I: = Integer (pfVar) to Integer (pfOut) do begin if I = Integer (pfAddress) then Continue; if TParamFlag (I) in AParamFlags then Result: = Result + ''+ GetEnumName (TypeInfo (TParamFlag), I); end; var MethodTypeData: PTypeData; ParamData: PParamData; TypeStr: p1_string; I: Integer; begin MethodTypeData: = GetTypeData (ATypeInfo); AStrings. add ('---------------------------------'); AStrings. add ('method Name: '+ ATypeInfo ^. name); AStrings. add ('method Kind: '+ GetEnumName (TypeInfo (TMethodKind), Integer (MethodTypeData ^. methodKind); AStrings. add ('params Count: '+ IntToStr (MethodTypeData ^. paramCount); AStrings. add ('params List: '); ParamData: = PParamData (@ MethodTypeData ^. paramList); for I: = 1 to MethodTypeData ^. paramCount do begin TypeStr: = Pointer (Integer (@ ParamData ^. paramName) + Length (ParamData ^. paramName) + 1); AStrings. add (Format ('[% s] % s: % s', [GetParamFlagsName (ParamData ^. flags), ParamData ^. paramName, TypeStr ^]); ParamData: = PParamData (Integer (ParamData) + SizeOf (TParamFlags) + Length (ParamData ^. paramName) + Length (TypeStr ^) + 2); end; if MethodTypeData ^. methodKind = mkFunction then AStrings. add ('result Value: '+ p1_string (ParamData) ^); end;

As an experiment, place a TListBox in the form and execute the following code to observe the execution result:

type  TMyMethod = function(A: array of Char; var B: TObject): Integer of object;procedure TForm1.FormCreate(Sender: TObject);begin  GetMethodTypeInfo(TypeInfo(TMyMethod), ListBox1.Items);  GetMethodTypeInfo(TypeInfo(TMouseEvent), ListBox1.Items);  GetMethodTypeInfo(TypeInfo(TKeyPressEvent), ListBox1.Items);  GetMethodTypeInfo(TypeInfo(TMouseWheelEvent), ListBox1.Items);end;

Because the type information of the method is complex, I try to compress the code as long as possible. Let's take a look at its implementation principles. The first parameter of GetMethodTypeInfo is of the PTypeInfo type, indicating the type information address of the method. The second parameter is a string list, which can be any object that implements the TStrings operation. We can use the TypeInfo function in System. pas to obtain RTTI information pointers of any type. The TypeInfo function is built into the compiler like SizeOf.

GetMethodTypeInfo also uses the GetEnumName function in TypInfo. pas. This function obtains the name of the enumerated type through an integer of the enumerated type.

function GetEnumName(TypeInfo: PTypeInfo; Value: Integer): string;

Similar to getting the property information of a class, the type information of a method is also in the TTypeData structure.

TTypeData = packed record case TTypeKind of tkMethod: (MethodKind: TMethodKind; // method pointer type ParamCount: Byte; // parameter quantity ParamList: array [0 .. 1023] of Char // For details about the parameter, see the downstream comments {ParamList: array [1 .. paramCount] of record Flags: TParamFlags; // parameter transfer rule ParamName: parameter string; // parameter name TypeName: parameter string; // parameter type end; ResultType: parameter string }); // Return Value Name end;

TMethodKind is a method type and is defined as follows:
TMethodKind = (mkProcedure, mkFunction, mkConstructor, mkDestructor,
MkClassProcedure, mkClassFunction,
{Obsolete}
MkSafeProcedure, mkSafeFunction );

TParamsFlags is the rule for passing parameters. It is defined as follows:

TParamFlag = (pfVar, pfConst, pfArray, pfAddress, pfReference, pfOut);TParamFlags = set of TParamFlag;

Since ParamName and TypeName are variable-length strings, you cannot directly use the value of this field. Instead, you should use the pointer step method to retrieve the parameter information, so the above Code looks long.

Obtains the RTTI information of the ordinal and set types.

After discussing the RTTI information of attributes and methods, it is much easier to look at the RTTI information of other data types. All the principles for obtaining RTTI are to get the TTypeData pointer through the GetTypeData function, and then parse TTypeData through TTypeInfo. TypeKind. The TTypeInfo pointer of any data type can be obtained through the TypeInfo function.

The TTypeData of the ordered type is defined as follows:

TTypeData = packed record tkInteger, tkChar, struct, tkSet, tkWChar: (OrdType: TOrdType; // case TTypeKind of tkInteger, tkChar, tkEnumeration, tkWChar: (MinValue: Longint; // minimum MaxValue: Longint; // maximum case TTypeKind of tkInteger, tkChar, tkWChar: (); tkEnumeration: (BaseType: PPTypeInfo; // pointer, which points to the enumerated PTypeInfo NameList: policstringbase; // The enumerated name string (cannot be used directly) EnumUnitName: policstringbase )); // The name of the unit to which it belongs (cannot be used directly) tkSet: (CompType: PPTypeInfo); // point to the end of the RTTI pointer of the set base class;

The following is a function for obtaining RTTI information of the ordered type and set type:

procedure GetOrdTypeInfo(ATypeInfo: PTypeInfo; AStrings: TStrings);var  OrdTypeData: PTypeData;  I: Integer;begin  OrdTypeData := GetTypeData(ATypeInfo);  AStrings.Add('------------------------------------');  AStrings.Add('Type Name: ' + ATypeInfo^.Name);  AStrings.Add('Type Kind: ' + GetEnumName(TypeInfo(TTypeKind),    Integer(ATypeInfo^.Kind)));  AStrings.Add('Data Type: ' + GetEnumName(TypeInfo(TOrdType),    Integer(OrdTypeData^.OrdType)));  if ATypeInfo^.Kind <> tkSet then  begin    AStrings.Add('Min Value: ' + IntToStr(OrdTypeData^.MinValue));    AStrings.Add('Max Value: ' + IntToStr(OrdTypeData^.MaxValue));  end;  if ATypeInfo^.Kind = tkSet then    GetOrdTypeInfo(OrdTypeData^.CompType^, AStrings);  if ATypeInfo^.Kind = tkEnumeration then    for I := OrdTypeData^.MinValue to OrdTypeData^.MaxValue do      AStrings.Add(Format('  Value %d: %s', [I, GetEnumName(ATypeInfo, I)]));end;

Place a TListBox in the form and run the following code to view the result:

type  TMyEnum = (EnumA, EnumB, EnumC);procedure TForm1.FormCreate(Sender: TObject);begin  GetOrdTypeInfo(TypeInfo(Char), ListBox1.Items);  GetOrdTypeInfo(TypeInfo(Integer), ListBox1.Items);  GetOrdTypeInfo(TypeInfo(TFormBorderStyle), ListBox1.Items);  GetOrdTypeInfo(TypeInfo(TBorderIcons), ListBox1.Items);  GetOrdTypeInfo(TypeInfo(TMyEnum), ListBox1.Items);end;

(If the enumeration element is not defined based on the default 0 reference, RTTI information cannot be generated. Why ?)

Obtains RTTI information of other data types.

We have discussed the running of several typical RTTI information. The methods for obtaining RTTI information of other data types are similar to those described above. Since these operations are simpler, we will not discuss them one by one. The following describes other types of RTTI information:

LongString, WideString, and Variant have no RTTI information;
Optional string only contains MaxLength information;
Only FloatType: TFloatType information;
 

TFloatType = (ftSingle, ftDouble, ftExtended, ftComp, ftCurr);

Int64 only contains the maximum and minimum values (also expressed as 64-bit integers );
Interface and dynamic array are not very familiar.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.