对于给定的类,我希望具有跟踪功能,即我希望记录每个方法调用(方法签名和实际参数值)和每个方法退出(只记录方法签名)。
假设存在以下情况,我该如何完成此操作:
我不想为C#,,
,
为了让问题更具体,让我们假设有3个类:
public class Caller
{
public static void Call()
{
Traced traced = new Traced();
traced.Method1();
traced.Method2();
}
}
public class Traced
{
public void Method1(String name, Int32 value) { }
public void Method2(Object object) { }
}
public class Logger
{
public static void LogStart(MethodInfo method, Object[] parameterValues);
public static void LogEnd(MethodInfo method);
}
如何为每个对Method1和Method2的调用调用Logger.LogStart和Logger.LogEnd,而不修改Caller.Call方法,也不显式地将调用添加到Traced.Method1和Traced.Method2
编辑:如果允许我稍微更改调用方法,那么解决方案是什么?
发布于 2008-08-25 09:31:41
C#不是一种面向面向方面的语言。它有一些面向方面的特性,你可以模仿其他的特性,但是用C#进行面向方面的编程是很痛苦的。
我一直在寻找做你想做的事情的方法,但我发现没有简单的方法去做。
据我所知,这就是你想要做的:
[Log()]
public void Method1(String name, Int32 value);
要做到这一点,你有两个主要选择
最后一种选择是使用IoC framework。也许这并不是一个完美的解决方案,因为大多数IoC框架都是通过定义允许方法挂钩的入口点来工作的,但是,根据您想要实现的目标,这可能是个不错的选择。
发布于 2008-08-25 09:41:13
要实现这一点,最简单的方法可能是使用PostSharp。它根据你应用的属性在你的方法中注入代码。它可以让你做你想做的事情。
另一种选择是使用profiling API在方法内部注入代码,但这是真正的核心。
发布于 2016-12-14 03:07:25
您可以使用Castle Windsor等DI容器的Interception特性来实现它。实际上,可以这样配置容器:具有由特定属性修饰的方法的每个类都将被拦截。
关于第三点,OP要求一个没有AOP框架的解决方案。在下面的回答中,我假设应该避免的是方面、JointPoint、PointCut等。根据Interception documentation from CastleWindsor的说法,这些都不是完成所要求的内容所必需的。
基于属性的存在配置侦听器的一般注册:
public class RequireInterception : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (HasAMethodDecoratedByLoggingAttribute(model.Implementation))
{
model.Interceptors.Add(new InterceptorReference(typeof(ConsoleLoggingInterceptor)));
model.Interceptors.Add(new InterceptorReference(typeof(NLogInterceptor)));
}
}
private bool HasAMethodDecoratedByLoggingAttribute(Type implementation)
{
foreach (var memberInfo in implementation.GetMembers())
{
var attribute = memberInfo.GetCustomAttributes(typeof(LogAttribute)).FirstOrDefault() as LogAttribute;
if (attribute != null)
{
return true;
}
}
return false;
}
}
将创建的IContributeComponentModelConstruction添加到容器中
container.Kernel.ComponentModelBuilder.AddContributor(new RequireInterception());
你可以在拦截器中做任何你想做的事情
public class ConsoleLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.Writeline("Log before executing");
invocation.Proceed();
Console.Writeline("Log after executing");
}
}
将日志属性添加到要记录的方法中
public class Traced
{
[Log]
public void Method1(String name, Int32 value) { }
[Log]
public void Method2(Object object) { }
}
请注意,如果只需要截获某个类的某些方法,则需要对该属性进行一些处理。默认情况下,所有公共方法都将被拦截。
https://stackoverflow.com/questions/25803
复制相似问题