Wednesday, January 6, 2016

Logging von anonymen Proceduren...

Anonymen Proceduren...

Anonymen Proceduren nutze ich eigentlich oft, ständig, fast nur noch... :-)

Anonymen Proceduren bringen den Sourcecode an die Stellen "wo" ich "ihn" brauche bzw. wenn ich den Sourcecode nochmal lese, kann ich sofort sehen was an dieser Stelle passiert.

Das macht natürlich nur Sinn, wenn ich den Code nicht an anderer Stelle nochmal brauche, da bietet sich selbstverständlich weiterhin eine "normale" Procedure an.

Jetzt nutze ich natürlich mein FDK und alle darin enthaltenen Funktionen. Das FDK bietet umfangreiche Logging-Funktionen. Das klappt auch bis auf eine Kleinigkeit sehr gut.
Ich konnte bisher nicht loggen, welche Procedure des Parameters ausgerufen wurde.

Beispiel:
procedure Foo<T>(AInvoke : TProc)
begin
   ...
   // Log(AInvoke)
   ...
end;

Mit vielen Dank an Remy Lebeau (TeamB) für eine Lösung:

type

  TFDKProcLogHelper = class abstract
    public
      class function Proc2String(P : Pointer) : String;
  end;

class function TFDKProcLogHelper.Proc2String(P : Pointer): String;
type
  PIInterface = ^IInterface;
var
  UnitName : String;
  Ctx: TRttiContext;
  ProcType : TRttiType;
  obj      : TInterfacedObject;
begin
  obj := PIInterface(P)^ as TInterfacedObject;
  UnitName := obj.UnitName;
  Ctx := TRttiContext.Create;
  try
    ProcType := Ctx.GetType(obj.ClassType);
  finally
    Ctx.Free;
  end;

  Result := '"'+UnitName+'.'+ProcType.ToString+'"';
end;
Jetzt kann ich ich loggen mit:
procedure Foo<T>(AInvoke : TProc)
begin
   ...
  FDKConfig.GetLogger( Self ).Debug( 'Foo<%s>(%s)', [
    PTypeInfo( TypeInfo( T ) ).Name,
      TFDKProcLogHelper.Proc2String(@AInvoke) ] );
   ...
end;

Und wieder ist ein Puzzelsteinchen für's FDK fertig.