2009-07-16 14 views
2

Gibt es eine Möglichkeit in C# eine zufällige Methode als Parameter zu übergeben?Eine zufällige Methode als Parameter übergeben?

meine Frage zu erklären:

Ich mag ein einfaches Logger-Tool schreiben, die die Ein- und Austritt eines Verfahrens mit den übergebenen Argumenten eine der Klassen- und Methodennamen berichten:

Des Protokolldatei ich bin mit dem Ziel an:

ENTERING: ClassOfDoom::MethodOfDoom(arg1={1} [int], arg2={true} [bool]) 
LEAVING: ClassOfDoom::MethodOfDoom RETURNING 1 [int] 

Der Code, den ich im Sinn haben:

class ClassOfDoom { 
    // Remeber: MethodOfDoom is a _random_ method with _random_ arguments 
    public int MethodOfDoom(int arg1, bool arg2) { 
    Log.Entering(this, this.MethodOfDoom, arg1, arg2); 
    ... 
    return Log.Returing(this, this.MethodOfDoom, 1); 
    } 
} 

Gibt es einen Weg, dies zu erreichen? Oder ist nicht C# so flexibel wie das?

Vielen Dank im Voraus!

Antwort

5

Sie können Ihre Protokollierungsfunktion ein MethodBase Argument nehmen und MethodBase.GetCurrentMethod verwenden, um die aktuelle Methodeninformation als ein Argument zu übergeben.

Dann könnten Sie im Logger seine Eigenschaften Name und DeclaringType überprüfen, um die Methodeninformationen zu erhalten. Auch ist Parameter übergeben einfach durch einen params object[] args Parameter in der Logging-Funktion erklärt:

public static void Entering(object obj, MethodBase methodInfo, 
          params object[] args) { 
    Console.WriteLine("ENTERING {0}:{1}", methodInfo.DeclaringType.Name, 
              methodInfo.Name); 
    ... 
} 
+0

Großartig! Es hat es geschafft! –

3

Ich bin nicht sicher, ob ich völlig verstehe Ihre Frage, aber wenn Sie versuchen, einen Anruf zu Log.Entering und Log zu machen. Wenn Sie innerhalb einer beliebigen (zufälligen) Methode zurückkehren und die tatsächlichen Parameter der Methode verwenden, sollten Sie PostSharp auschecken. Es ermöglicht Ihnen, Code in einen Methodenkörper zu injizieren und dann einige Arbeit zu tun, basierend auf den reflektierten Methodeninformationen, die Sie vom .NET-Framework erhalten (und den tatsächlichen Parametern, die zur Laufzeit an die Methode übergeben werden).

2

Wenn dieses Szenario in Ihrem Code weit verbreitet ist, wird es am besten mit Aspect-Oriented-Programming (AOP) -Techniken implementiert. Es gibt verschiedene Frameworks, die verwendet werden können (z. B. Spring.NET AOP), die Sie in Ihrer .NET-Anwendung verwenden können. Hier ist ein Referenzartikel, die Ihnen helfen loszulegen:

http://www.developer.com/lang/article.php/10924_3795031_2

Die referenzierte Artikel gibt Ihnen die Protokollierung eingeben/Exit-Szenario als Beispiel.

+0

Hinweis: Die PostSharp-Referenz von Benutzer Lck ist ein weiteres AOP-Framework, das Sie auschecken können. –

3

Sie könnte es tun mit Expression leicht genug - es ist etwas aussehen würde:

Log.Capture(() => this.MethodOfDoom(arg1, arg2)); 

Hier ist ein Beispiel; Ich habe ein bisschen faul gewesen Compile().DynamicInvoke() mit den arg-Werte lesen - für echten Code würde ich versuchen, es zu lesen, mehr direkt:

using System; 
using System.Diagnostics; 
using System.Linq.Expressions; 
class Program 
{ 
    DateTime MethodOfDoom(string s, int i) 
    { 
     return DateTime.Today; 
    } 
    public void RunTest() 
    { 
     int i =123; 
     Log.Capture(() => this.MethodOfDoom("abc", i)); 
    } 
    static void Main() 
    { 
     new Program().RunTest(); 
    } 
} 
static class Log 
{ 
    public static T Capture<T>(Expression<Func<T>> method) 
    { 
     MethodCallExpression mce = method.Body as MethodCallExpression; 
     if (mce == null) throw new InvalidOperationException(
      "Method-call expected"); 
     string name = mce.Method.Name; 
     try 
     { 
      int i = 0; 
      foreach(var param in mce.Method.GetParameters()) 
      { 
       object argValue = Expression.Lambda(mce.Arguments[i++]) 
         .Compile().DynamicInvoke(); 
       Trace.WriteLine(param.Name + "=" + argValue, name); 
      } 
      Trace.WriteLine("ENTERING", name); 
      T result = method.Compile().Invoke(); 
      Trace.WriteLine("EXITING: " + result, name); 
      return result; 
     } 
     catch (Exception ex) 
     { 
      Trace.WriteLine("EXCEPTION: " + ex, name); 
      throw; 
     } 
    } 
} 
+1

+1. Tolle Idee für dieses Problem.Obwohl ich kaum sagen kann, dass es "die Methode passiert". –

+0

Ja, toller Code, aber nicht das, wonach ich suche. –

0

I Postsharp verwendet haben, bevor Sie diese sehr Sache zu tun.

Verwandte Themen