在Python中,我可以使用装饰器来跟踪函数调用、它的变量和返回值。 它非常容易使用。 我只是想知道 C# 可以做同样的事情吗?
我发现网上有CallTracing Attribute的示例代码。 然而,它并没有达到我预期的结果。
C# 属性与 Python 的装饰器有类似的概念吗?
[AttributeUsage(AttributeTargets.Method | AttributeTargets.ReturnValue |
AttributeTargets.Property, AllowMultiple = false)]
public class CallTracingAttribute : Attribute
{
public CallTracingAttribute()
{
try
{
StackTrace stackTrace = new StackTrace();
StackFrame stackFrame = stackTrace.GetFrame(1);
Trace.TraceInformation("{0}->{1} {2}:{3}",
stackFrame.GetMethod().ReflectedType.Name,
stackFrame.GetMethod().Name,
stackFrame.GetFileName(),
stackFrame.GetFileLineNumber());
Debug.WriteLine(string.Format("{0}->{1} {2}:{3}",
stackFrame.GetMethod().ReflectedType.Name,
stackFrame.GetMethod().Name,
stackFrame.GetFileName(),
stackFrame.GetFileLineNumber()));
}
catch
{
}
}
}
class Program
{
[CallTracing]
static int Test(int a)
{
return 0;
}
[CallTracing]
static void Main(string[] args)
{
Test(1);
}
}
.NET 确实支持调用拦截架构,如果您愿意接受一些约束(即从 ContextBoundObject 派生等)。 您可以在标题为“通过将自定义服务注入对象的拦截链来解耦组件”的 MSDN 杂志文章中找到有关如何执行此操作的完整说明。
此外,您可能需要考虑将类抽象为接口,然后通过接口实现转发调用来拦截调用。
最后看一下WCF。 它有一个非常明确的拦截架构(不要让它的 Web 服务欺骗了你,你可以简单地创建你自己的通道传输,这是一个空通道),你可以利用它来完成你想要的事情。
C# 不支持开箱即用的 AOP。为此,您需要像 PostSharp 这样的 IL 重写器。
您可以使用 Runtime Flow 工具(由我开发)跟踪所有 .NET 函数调用、参数和返回值,而无需手动添加装饰器。