我们正尝试使用 AOP 在我们的应用程序中实现日志记录(顺便说一下,还有 PostSharp,但这个问题与任何 AOP 框架有关)。
我们面临的问题是,我们得到的信息是这样的:
使用参数输入方法 XXX:
- 参数内容(如果是值类型)。
- ToString() 中的任何内容(如果已完成)都会覆盖。
- 类名,如果 ToString() 未被覆盖。
这些信息不是很有用,因为通常我们得到的是第 3 种情况。我们还在创建许多无用的信息。
如果您使用 AOP 登录任何产品,您是如何管理这个问题的?
提前谢谢。
几种方法:
-
在要记录的类型上放置一个通用接口。(例如,ILoggable)。实现该接口将使您的方面能够准确记录您想要的内容。缺点是您必须为可能记录的每个对象实现/维护 ILoggable。
-
使用反射(这是我在博客上的这个审计示例中所做的。它使用MVC ActionFilter,但原理是相同的)。权衡在博客文章中详细说明,但基本上是使用反射和性能问题的复杂性,具体取决于您记录的量和频率。
-
使用序列化。给定一个对象,将其序列化为 Json 或 XML 或其他对象,并记录该字符串。根据您对日志执行的操作,这可能从完美到毫无价值,并且取决于序列化的工作方式和对象的复杂程度,这也可能是性能问题。
我致力于一种新的AOP框架,以响应现有AOP框架中缺少的功能。你可以在这里找到我的开源项目:NConcern .NET AOP Framework
与其他方法的区别之一是允许您使用 System.Linq.Expression 开发您的建议,以避免基于类型的装箱/取消装箱、反射和哈希跳转。对于初学者来说,使用 Expression 进行开发有点困难,但对于高级开发人员来说很容易。
举一个简单的登录示例(进入控制台),而无需重写您的业务、反射和装箱。
A 业务 : 计算器
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
您的日志记录方面由 linq 表达式实现,用于描述建议必须如何工作。
public class Logging : IAspect
{
//this is not an advice, this method is called to produce advices
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
//generic presentation method
var presentation = typeof(Presentation). GetMethod("Of");
//example log on exception
//instance, arguments and exception are Expressions
yield return Advice.Linq.After.Throwing((instance, arguments, exception) =>
{
Expression.Call
(
typeof(Console).GetMethod("WriteLine",...),
Expression.Call
(
typeof(string).GetMethod("Concat", new Type[] { typeof(string[]) }),
Expression.NewArrayInit(typeof(string), arguments.Select(argument => argument.Type == typeof(string) ? argument : ...).ToArray())
)
)
}
}
}