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#不灵活吗?
提前致谢!
答案 0 :(得分:5)
您可以使您的日志记录功能采用MethodBase
参数,并使用MethodBase.GetCurrentMethod将当前方法信息作为参数传递。
然后,在记录器中,您可以检查其属性Name
和DeclaringType
以获取方法信息。此外,通过在日志记录函数中声明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来做这件事。