2010-10-02 2 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, чтобы узнать, есть ли оно mkFunction или mkClassFunction и т. Д. По мере необходимости. MethodKind возвращение товара mkProcedure если HasExtendedInfo есть False.

0

Функция IsFunction в большинстве случаев должна работать нормально. Но для некоторых функций для них нет RTTI, поскольку их параметры включают типы, которые не имеют RTTI, например TBytes или array of const. Но для большинства функций ваша функция будет работать. I just hope that the omissions get filled in by the next version.