2

我需要确定 aTRttiMethod是否是一个函数

到目前为止,我写了这个函数

Function IsFunction(QualifiedName,MethodName:string):Boolean;
Var
  ctx     : TRttiContext;
  lType   : TRttiType;
  lMethod : TRttiMethod;
Begin
    result:=false;
    ctx := TRttiContext.Create;
    lType:=ctx.FindType(QualifiedName);
    if Assigned(lType) then
    begin
       lMethod:=lType.GetMethod(MethodName);
         if Assigned(lMethod) then
           Result:=(lMethod.ReturnType<>nil); //in this line the exception is raised
    end;
End;

Insufficient RTTI available to support this operation.但是当我测试以下内容时,此功能失败并出现此异常

IsFunction('SysUtils.Exception','CreateFmt')

这些类和方法也失败了

SysUtils.Exception -> CreateFmt
SysUtils.Exception -> CreateResFmt
SysUtils.Exception -> CreateResFmt
SysUtils.Exception -> CreateFmtHelp
SysUtils.Exception -> CreateResFmtHelp
SysUtils.Exception -> CreateResFmtHelp
SysUtils.TEncoding -> Convert
SysUtils.TEncoding -> Convert
SysUtils.TEncoding -> GetBufferEncoding
SysUtils.TEncoding -> GetBufferEncoding
SysUtils.TEncoding -> GetByteCount
SysUtils.TEncoding -> GetByteCount
SysUtils.TEncoding -> GetByteCount
SysUtils.TEncoding -> GetByteCount
SysUtils.TEncoding -> GetBytes
SysUtils.TEncoding -> GetBytes
SysUtils.TEncoding -> GetBytes
SysUtils.TEncoding -> GetBytes
SysUtils.TEncoding -> GetBytes
SysUtils.TEncoding -> GetCharCount
SysUtils.TEncoding -> GetCharCount
SysUtils.TEncoding -> GetChars
SysUtils.TEncoding -> GetChars
SysUtils.TEncoding -> GetChars
SysUtils.TEncoding -> GetPreamble
SysUtils.TEncoding -> GetString
SysUtils.TEncoding -> GetString
SysUtils.TMBCSEncoding -> GetPreamble
SysUtils.TUTF8Encoding -> GetPreamble
SysUtils.TUnicodeEncoding -> GetPreamble
SysUtils.TBigEndianUnicodeEncoding -> GetPreamble
Rtti.TRttiMethod -> Invoke
Rtti.TRttiMethod -> Invoke
Rtti.TRttiMethod -> Invoke
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> AddRange
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> AddRange
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> AddRange
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> InsertRange
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> InsertRange
Generics.Collections.TList<Rtti.TMethodImplementation.TParamLoc> -> InsertRange
Generics.Collections.TArray -> Sort
Generics.Collections.TArray -> Sort
Generics.Collections.TArray -> Sort
Generics.Collections.TArray -> BinarySearch
Generics.Collections.TArray -> BinarySearch
Generics.Collections.TArray -> BinarySearch

我写了这个小应用程序来检查这种行为

program ProjectTest;

{$APPTYPE CONSOLE}

uses
  Rtti,
  SysUtils;

Function IsFunction(QualifiedName,MethodName:string):Boolean;
Var
  ctx     : TRttiContext;
  lType   : TRttiType;
  lMethod : TRttiMethod;
Begin
    result:=false;
    ctx := TRttiContext.Create;
    lType:=ctx.FindType(QualifiedName);
    if Assigned(lType) then
    begin
       lMethod:=lType.GetMethod(MethodName);
       try
         if Assigned(lMethod) then
           Result:=(lMethod.ReturnType<>nil);
       except on e : exception do
           Writeln(Format('%s %s -> %s',[e.Message,QualifiedName,MethodName]));
       end;
    end;
End;


var
  ctx     : TRttiContext;
  lType   : TRttiType;
  lMethod : TRttiMethod;
begin
  try
    ctx := TRttiContext.Create;
    for lType in  ctx.GetTypes do
       for lMethod in lType.GetDeclaredMethods do
         IsFunction(lType.QualifiedName,lMethod.Name);
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

确定 anTRttiMethod是否是函数的正确方法是什么?

更新

TRttiMethod感谢@Barry 的建议,我重写了函数以避免异常,但是由于RTTI 的当前限制,这并不能解决如何确定a 是否是函数的问题。

function IsFunction(lType : TRttiType;MethodName:string):Boolean;
Var
  ctx     : TRttiContext;
  lMethod : TRttiMethod;
Begin
    result:=false;
    if Assigned(lType) then
    begin
       lMethod:=lType.GetMethod(MethodName);
         if Assigned(lMethod) then
           if lMethod.HasExtendedInfo then
            Result:= (lMethod.MethodKind in [mkFunction,mkClassFunction]) //you can be 100 % sure, wich this is a function or not
           else // sorry but the RTTI does not provide this information when the TRttiMethod contains parameters or an resultype that are not supported by the RTTI
             Result:=False;
    end;
End;
4

2 回答 2

9

您可以检查TRttiMethod.HasExtendedInfo以避免异常。该类会在尝试访问只有HasExtendedInfo返回时数据才可用的属性时抛出异常True

您可以根据需要考虑检查该MethodKind属性以查看它是否为mkFunctionmkClassFunction等。如果是则MethodKind返回。mkProcedureHasExtendedInfoFalse

于 2010-10-02T21:26:57.190 回答
0

在大多数情况下,您的 IsFunction 函数应该可以正常工作。但有些函数并没有为它们生成 RTTI,因为它们的参数包括没有 RTTI 可用的类型,例如TBytesarray of const。但是对于大多数功能,您的功能将起作用。 只希望下个版本能补上这些遗漏。

于 2010-10-02T20:35:28.900 回答