3

我正在用 C# 编写一个函数来记录用户在我们系统上的操作并将它们保存在数据库中。具体来说,我想在调用它们时记录某些业务逻辑功能。我想到了这样的日志记录方法:

public static LogMethod(string user, string methodName, object[] parameters, string message)

在方法内部,ToString()为每个参数调用适当的函数。例如,对于方法 Foo,它的调用方式如下:

void Foo(int a, SomeObject b)
{
     Logger.LogMethod(username, "Foo", new object[]{a,b}, "Beginning Foo");
     //etc
}

这是记录函数调用的好方法吗?实现此目的的最佳实践是什么?它会以不好的方式影响性能吗?

4

4 回答 4

3

是的,它会影响性能,因为您必须使用反射来获取 MethodInfo 然后调用它。除此之外,它会破坏可维护性,因为您无法重构方法名称。

查看以下先前的问答以获取替代方案:如何在 C# 中拦截方法调用?

于 2012-05-07T16:14:52.763 回答
3

不要在漂亮的业务逻辑中乱扔日志记录逻辑,这是一个横切关注点。您应该使用方法拦截之类的技术来拦截要记录的方法。

这是记录函数调用的好方法吗?

不,这不是,坦率地说。您的代码现在关注执行您的业务逻辑和日志记录。那是难以编写、难以测试且非常难以维护的代码。

实现此目的的最佳实践是什么?

我鼓励你找到一种方法来解决这个问题,而不涉及到处都记录代码来破坏你的代码。对此的标准解决方案是使用方法拦截或面向方面编程之类的东西。有很多方法可以实现这一点(您可以使用许多框架之一来设置它,但我偏爱 Castle Windsor)。

它会以不好的方式影响性能吗?

只有你可以回答那个问题。如果您正在记录用户正在执行的操作,则不太可能。用户既慢又笨,他们使用速度慢的磁盘和数据库之类的东西,因此不太可能关心您是否需要额外的几毫秒来记录某些内容。我们在这里不是在谈论关键循环。但是只有你可以决定它是否慢得不能接受,只有你可以测量你自己的应用程序有和没有日志记录,看看它是否慢得不能接受。

于 2012-05-07T16:15:01.617 回答
2

一切都会影响性能,但效果是否“坏”是主观的。它还完全取决于您调用该方法的频率。

如果您重新排列参数并使用params关键字,则可以简化调用:

public static LogMethod(string user, string methodName, string message, params object[] parameters)

现在你的电话更简单了:

Logger.LogMethod(username, "Foo", "Beginning Foo", a, b);

无需声明对象数组,编译器会为您处理这些。请参阅参数

此外,您可以通过从堆栈中获取调用方法名称来进一步简化调用:

public static LogMethod(string user, string message, params object[] parameters)
{
    string methodName = new StackFrame(1).GetMethod().Name;
    ...      
}

现在您不需要 methodName 参数。(在 .Net 4.5 中,您可以使用CallerMemberNameAttribute实现相同的目的。)

通过反思,您可以走得更远;例如,您可以获得传递给调用方法的参数的名称、类的名称等。

于 2012-05-07T16:21:33.087 回答
2

正如其他人已经指出的那样,AOP 框架可能是要走的路。


如果您仍然想使用您的方法,您可以对其进行小幅改进。如果将参数放在最后,则可以使用params关键字。

public static LogMethod(string user, string methodName, string message,
                        params object[] parameters)

这使得调用该方法更容易一些。

void Foo(int a, SomeObject b)
{
    Logger.LogMethod(username, "Foo", "Beginning Foo", a, b);
    //etc  
}  
于 2012-05-07T16:15:32.210 回答