传递随机方法作为参数?

时间:2009-07-16 10:12:14

标签: c#

C#是否有办法将随机方法作为参数传递?

解释我的问题:

我想写一个简单的Logger-Tool,它报告方法的输入和离开传递的参数和类和方法名称:

我的目标是:

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

我想到的代码:

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);
  }
}

有没有办法实现这个目标?或者 C#不灵活吗?

提前致谢!

5 个答案:

答案 0 :(得分:5)

您可以使您的日志记录功能采用MethodBase参数,并使用MethodBase.GetCurrentMethod将当前方法信息作为参数传递。

然后,在记录器中,您可以检查其属性NameDeclaringType以获取方法信息。此外,通过在日志记录函数中声明params object[] args参数来轻松传递参数:

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

答案 1 :(得分:3)

我不确定我是否完全理解你的问题,但如果你试图在任意(随机)方法内调用Log.Entering和Log.Returning并使用方法的实际参数,你应该看看{ {3}}。它允许您在方法体中注入代码,然后根据从.NET框架获得的反射方法信息(以及在运行时传递给方法的实际参数)执行一些工作。

答案 2 :(得分:3)

你可以轻松地使用Expression - 它看起来像:

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

这是一个例子;我使用Compile().DynamicInvoke()读取arg值时有点懒惰 - 对于真正的代码我会尝试直接读取它:

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;
        }
    }
}

答案 3 :(得分:2)

如果在代码中广泛使用,则最好使用面向方面编程(AOP)技术实现此方案。可以使用不同的框架(例如Spring.NET AOP),您可以在.NET应用程序中使用它们。以下是可能有助于您入门的参考文章:

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

参考文章为您提供了日志输入/退出方案作为示例。

答案 4 :(得分:0)

我之前使用PostSharp来做这件事。