2008-10-05 6 views

Antwort

4

Der beste Weg, um diese Art von Sache zu erreichen, ist mit Abfangen, gibt es eine Reihe von Möglichkeiten, dies zu tun, obwohl sie alle dazu neigen, etwas invasiv sein. Eine wäre, alle Ihre Objekte von ContextBoundObject abzuleiten. Here ist ein Beispiel für die Verwendung dieser Art von Ansatz. Der andere Ansatz wäre, eine der vorhandenen AOP-Bibliotheken zu verwenden, um dies zu erreichen. Etwas wie DynamicProxy von Castle Project ist der Kern von vielen von diesen. Hier sind ein paar Links: Spring.Net PostSharp Cecil

Es gibt wahrscheinlich mehr andere, und ich weiß, Castle Windsor und Ninject beide bieten AOP-Funktionen auf der IoC-Funktionalität.

Sobald AOP vorhanden ist, schreiben Sie einfach eine Interceptor-Klasse, die die Informationen über die Methodenaufrufe an log4net schreibt.

Ich wäre wirklich nicht überrascht, wenn eines der AOP-Frameworks Ihnen diese Art von Funktionalität aus der Box geben würde.

3

Sie könnten einen Post-Compiler wie Postsharp verwenden. Die Probe von der Website spricht über die Einrichtung eines Tracers für die Eingabe/Verlassen einer Methode, die sehr ähnlich ist, was Sie wollen.

4

Ich bin nicht sicher, was Ihre tatsächlichen Bedürfnisse sind, aber hier ist eine Low-Miete-Option. Es ist nicht gerade „Automatik“, aber man kann Stacktrace verwendet die Informationen, die Sie suchen in einer Art und Weise zu schälen, die nicht vorbei Argumente verlangen würden - ähnlich wie ckramer Vorschlag in Bezug auf Interception:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Diagnostics; 

namespace TracingSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      DoSomething(); 
     } 

     static void DoSomething() 
     { 
      LogEnter(); 

      Console.WriteLine("Executing DoSomething"); 

      LogExit(); 
     } 

     static void LogEnter() 
     { 
      StackTrace trace = new StackTrace(); 
      if (trace.FrameCount > 1) 
      { 
       string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace; 
       string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name; 
       Console.WriteLine("Entering {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name); 
      } 
     } 

     static void LogExit() 
     { 
      StackTrace trace = new StackTrace(); 
      if (trace.FrameCount > 1) 
      { 
       string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace; 
       string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name; 
       Console.WriteLine("Exiting {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name); 
      } 
     } 
    } 
} 

Sie könnten kombinieren so etwas wie das obige Beispiel mit Vererbung, einen nicht-virtuellen öffentlichen Member in dem Basistyp mit der Aktion-Methode, um anzuzeigen, dann ein virtuelles Mitglied Aufruf zu tun eigentliche Arbeit:

public abstract class BaseType 
{ 
    public void SomeFunction() 
    { 

     LogEnter(); 
     DoSomeFunction(); 
     LogExit(); 
    } 

    public abstract void DoSomeFunction(); 
} 

public class SubType : BaseType 
{ 
    public override void DoSomeFunction() 
    { 
     // Implementation of SomeFunction logic here... 
    } 
} 

wieder - es gibt nicht viel „Automatik "darüber, aber es würde auf einer begrenzten Basis funktionieren, wenn Sie Instrumentierung auf jedem einzelnen Methodenaufruf nicht benötigen würden aktion.

Hoffe, das hilft.

+1

Dieser Code geht auch mit diesem Code, um die Parameter zu erfassen Werte http://stackoverflow.com/a/6928253/1267778. Also habe ich etwas wie logService.LogEnter (arg1, arg2, arg3). Tolles Zeug – parliament

0

Sie können das Open-Source-Framework CInject auf CodePlex verwenden, das über einen LogInjector verfügt, um den Eingang und das Ende eines Methodenaufrufs zu markieren.

Oder Sie können die Schritte ausführen, die in diesem Artikel auf Intercepting Method Calls using IL erwähnt werden, und Ihren eigenen Interceptor erstellen, der Reflection.Emit-Klassen in C# verwendet.

0

Funktionen

auf Jared Antwort zu erweitern, Code Wiederholung zu vermeiden und einschließlich options for arguments:

private static void LogEnterExit(bool isEnter = true, params object[] args) 
{ 
    StackTrace trace = new StackTrace(true); // need `true` for getting file and line info 
    if (trace.FrameCount > 2) 
    { 
     string ns = trace.GetFrame(2).GetMethod().DeclaringType.Namespace; 
     string typeName = trace.GetFrame(2).GetMethod().DeclaringType.Name; 
     string args_string = args.Length == 0 ? "" : "\narguments: [" + args.Aggregate((current, next) => string.Format("{0},{1};", current, next))+"]"; 
     Console.WriteLine("{0} {1}.{2}.{3}{4}", isEnter ? "Entering" : "Exiting", ns, typeName, trace.GetFrame(2).GetMethod().Name, args_string); 
    } 
} 

static void LogEnter(params object[] args) 
{ 
    LogEnterExit(true, args); 
} 

static void LogExit(params object[] args) 
{ 
    LogEnterExit(false, args); 
} 

Nutzungs

static void DoSomething(string arg1) 
{ 
    LogEnter(arg1); 
    Console.WriteLine("Executing DoSomething"); 
    LogExit(); 
} 

Ausgabe

in der Konsole dies wäre der Ausgabe wenn DoSomething mit "blah" als 012 ausgeführt wurden

Entering Program.DoSomething 
arguments: [blah] 
Executing DoSomething 
Exiting Program.DoSomething 
Verwandte Themen