delphi – 如何获取方法指针指向的方法的名称?

前端之家收集整理的这篇文章主要介绍了delphi – 如何获取方法指针指向的方法的名称?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经定义了以下内容

>一个方法指针,如果验证正常或错误代码则返回0

TValidationFunc = Function(AParam: TAnObject): integer Of Object;

>要执行的功能列表:

Functions: TObjectList < TValidationFunc>;

我在函数列表中放了几个带有此签名的函数.

为了执行它们,我执行:

For valid In Functions Do
Begin
  res := -1;
  Try
    res := valid(MyObject);
  Except
    On E: Exception Do
      Log('Error in function ??? : ' + E.Message,TNiveauLog.Error,'PHVL');
  End;
  Result := Result And (res = 0);
End;

如果此函数引发异常,我如何在日志中获取原始函数名称

解决方法

好吧,永远不要说永远:-).对于将其作为参数传递的事件,此函数将返回方法名称(格式为< ClassType>.< MethodName> ie.TMainForm.FormCreate).遗憾的是,您不能使用无类型参数来允许传入任何类型的事件,但必须为您希望能够“解码”的每个方法签名编写特定例程:
FUNCTION MethodName(Event : TValidationFunc) : STRING;
  VAR
    M   : TMethod ABSOLUTE Event;
    O   : TObject;
    CTX : TRttiContext;
    TYP : TRttiType;
    RTM : TRttiMethod;
    OK  : BOOLEAN;

  BEGIN
    O:=M.Data;
    TRY
      OK:=O IS TObject;
      Result:=O.ClassName
    EXCEPT
      OK:=FALSE
    END;
    IF OK THEN BEGIN
      CTX:=TRttiContext.Create;
      TRY
        TYP:=CTX.GetType(O.ClassType);
        FOR RTM IN TYP.GetMethods DO
          IF RTM.CodeAddress=M.Code THEN
            EXIT(O.ClassName+'.'+RTM.Name)
      FINALLY
        CTX.Free
      END
    END;
    Result:=IntToHex(NativeInt(M.Code),SizeOf(NativeInt)*2)
  END;

像这样用它:

For valid In Functions Doc Begin
  res := -1;
  Try
    res := valid(MyObject);
  Except
    On E: Exception Do
      Log('Error in function '+MethodName(valid)+' : ' + E.Message,'PHVL');
  End;
  Result := Result And (res = 0);
End;

我没有用上面的代码试过它,但是用我的MainForm的FormCreate尝试过.

有一点需要注意:这只适用于生成RTTI的方法,而且只适用于Delphi 2010及更高版本(它们大大增加了RTTI可用的数据量).因此,为了确保它有效,您应该将要跟踪的方法放在PUBLISHED部分中,因为这些方法始终(默认情况下)将生成RTTI.

如果你想要它更一般,你可以使用这个结构:

FUNCTION MethodName(CONST M : TMethod) : STRING; OVERLOAD;
  VAR
    O   : TObject;
    CTX : TRttiContext;
    TYP : TRttiType;
    RTM : TRttiMethod;
    OK  : BOOLEAN;

  BEGIN
    O:=M.Data;
    TRY
      OK:=O IS TObject;
      Result:=O.ClassName
    EXCEPT
      OK:=FALSE
    END;
    IF OK THEN BEGIN
      CTX:=TRttiContext.Create;
      TRY
        TYP:=CTX.GetType(O.ClassType);
        FOR RTM IN TYP.GetMethods DO
          IF RTM.CodeAddress=M.Code THEN
            EXIT(O.ClassName+'.'+RTM.Name)
      FINALLY
        CTX.Free
      END
    END;
    Result:=IntToHex(NativeInt(M.Code),SizeOf(NativeInt)*2)
  END;

FUNCTION MethodName(Event : TValidationFunc) : STRING; OVERLOAD; INLINE;
  BEGIN
    Result:=MethodName(TMethod(Event))
  END;

然后你只需要为每个只调用一般实现的事件编写一个特定的MethodName,如果你把它标记为INLINE,它很可能甚至不会产生额外的函数调用,而是直接调用它.

顺便说一句:我的答复很大程度上受到Cosmin Prund一年前在这个问题中给出的代码的影响:RTTI information for method pointer

如果您的Delphi没有定义NativeInt(无法记住它们何时实现它),只需将其定义为:

{$IFNDEF cpuX64 }
TYPE
  NativeInt = INTEGER;
{$ENDIF }

猜你在找的Delphi相关文章