代码之家  ›  专栏  ›  技术社区  ›  RRUZ

如何确定TRttiMethod是否是函数

  •  2
  • RRUZ  · 技术社区  · 16 年前

    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公司 是函数吗?

    更新

    由于@Barry的建议,我重写了函数以避免异常,但是这并不能解决如何确定 是否是一个函数,取决于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;
    
    2 回复  |  直到 16 年前
        1
  •  9
  •   Barry Kelly    16 年前

    你可以查一下 TRttiMethod.HasExtendedInfo HasExtendedInfo 退货 True .

    你可以考虑检查一下 MethodKind 属性来查看它是否 mkFunction 或 mkClassFunction MethodKind公司 退货 mkProcedure 已扩展信息 是 False .

        2
  •  0
  •   Mason Wheeler    16 年前