2010-10-02 58 views
2

我需要確定一個TRttiMethod是一個功能如何確定一個TRttiMethod是一個功能

到目前爲止,我寫了這個功能

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. 

這是確定的TRttiMethod是一個函數的正確方法是什麼?

UPDATE

得益於@Barry建議,我改寫了功能,以避免該異常,但是這並沒有解決如何確定一個TRttiMethod是一個函數或不是由於目前的侷限性問題的RTTI。

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; 

回答

9

您可以檢查TRttiMethod.HasExtendedInfo以避免此例外。如果HasExtendedInfo返回True,則該類將拋出一個例外,以嘗試訪問只有數據可用的屬性。

您可以考慮檢查MethodKind屬性以查看它是否爲mkFunctionmkClassFunction等。 MethodKind返回mkProcedure如果HasExtendedInfoFalse

0

在大多數情況下,您的IsFunction函數應該可以正常工作。但是某些函數沒有爲它們生成RTTI,因爲它們的參數包括沒有RTTI可用的類型,例如TBytesarray of const。但對於大多數功能,您的功能將起作用。 I just hope that the omissions get filled in by the next version.