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 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |