我在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
}
这是记录函数调用的好方法吗?实现此目的的最佳实践是什么? 它会以一种糟糕的方式影响性能吗?
答案 0 :(得分:3)
是的,它会影响性能,因为您必须使用反射来获取MethodInfo然后再调用它。除此之外,它会破坏可维护性,因为你无法重构方法名称。
请查看以下先前的问答答以获取替代方案:How do I intercept a method call in C#?
答案 1 :(得分:3)
不要使用记录逻辑来破坏您美丽的业务逻辑,这是一个贯穿各领域的问题。您应该使用类似方法拦截的技术来拦截您要记录的方法。
记录函数调用是一种好方法吗?
不,坦白说,不是。您的代码现在关注的是执行业务逻辑和日志记录。这是难以编写,难以测试且难以维护的代码。
实现此目的的最佳做法是什么?
我鼓励您找到一种解决此问题的方法,该方法不涉及在任何地方使用日志记录代码破坏您的代码。对此的标准解决方案是使用类似方法拦截或面向方面编程之类的东西。有很多方法可以实现这一点(你可以使用其中一个框架来设置它,但我偏爱Castle Windsor)。
它会以不好的方式影响表现吗?
只有你能回答这个问题。如果您正在记录用户正在做的事情,则不太可能。用户很慢而且愚蠢,他们使用的磁盘和数据库都很慢,因此如果你花费额外的几毫秒来记录某些内容,则不太在意。我们这里不是在讨论关键循环。 但只有你可以决定它是否慢得令人无法接受,并且只有你可以测量你自己的应用程序,无论是否有记录,都可以看看它是否慢得令人无法接受。
答案 2 :(得分: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
}
答案 3 :(得分:2)
一切都会影响表现,但效果是否“不好”是主观的。它也完全取决于你调用方法的频率。
如果您重新插入参数并使用params
关键字,则可以简化呼叫:
public static LogMethod(string user, string methodName, string message, params object[] parameters)
现在你的电话更简单了:
Logger.LogMethod(username, "Foo", "Beginning Foo", a, b);
没有必要声明对象数组,编译器会为您处理这个问题。请参阅params。
此外,您可以通过从堆栈中获取调用方法名称来进一步简化调用:
public static LogMethod(string user, string message, params object[] parameters)
{
string methodName = new StackFrame(1).GetMethod().Name;
...
}
现在您不需要methodName参数。 (在.Net 4.5中,您可以使用CallerMemberNameAttribute实现相同的目标。)
通过反思你可以走得更远;例如,您可以获取传递给调用方法的参数的名称,类的名称等。