C# 如何跟踪调用的每个方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14862635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:15:47  来源:igfitidea点击:

How to trace every method called

c#loggingtrace

提问by ShaQ.Blogs

I have an existing project where I would like to find out all calls being made and maybe dump into a log file.

我有一个现有的项目,我想在其中找出所有正在进行的调用,并可能转储到日志文件中。

I had a look at this thread, but didnt help much. I tried PostSharp, and the example shows how to achieve it. But I need to add an attribute to every darn method. Being an existing project, with in-numerous methods that is not a feasible option.

我看过这个线程,但没有太大帮助。我尝试了 PostSharp,示例显示了如何实现它。但是我需要为每个该死的方法添加一个属性。作为一个现有的项目,有无数的方法不是一个可行的选择。

Is there any other means by which I can quickly trace all calls made?

有没有其他方法可以快速跟踪所有调用?

回答by gideon

You can do this with Unity Interception

你可以用Unity Interception做到这一点

See this article for a sample. The article uses attributes, but my code sample below use the dependency injection system (coding to an interface) to setup interception.

请参阅本文以获取示例。这篇文章使用了属性,但我下面的代码示例使用依赖注入系统(编码到接口)来设置拦截。

If you want to log MyClass, it goes something like this:

如果你想记录MyClass,它会是这样的:

  1. Make an interface that contains all methods in MyClass=> IMyClass
  2. You setup InterfaceInterception (like I've done below) OR there are a few other ways you can set it up. See here for all options.
  3. You'll setup a policy to intercept all methods that matches IMatchingRule.
  4. All calls will now be intercepted by your ICallHandlerimplementation.
  1. 制作一个包含MyClass=>中所有方法的接口IMyClass
  2. 您设置 InterfaceInterception(就像我在下面所做的那样)或者还有其他一些方法可以设置它。请参阅此处了解所有选项
  3. 您将设置一个策略来拦截所有匹配的方法IMatchingRule
  4. 现在,您的ICallHandler实现将拦截所有调用。

Code:

代码:

//You  will use the code like this:
MyContainer container = new MyContainer();
//setup interception for this type..
container.SetupForInteception(typeof(IMyClass));
 //what happens here is you get a proxy class 
 //that intercepts every method call.
IMyClass cls = container.Resolve<IMyClass>();

 //You need the following for it to work:   
public class MyContainer: UnityContainer
{
    public MyContainer()
    {
        this.AddNewExtension<Interception>();
        this.RegisterType(typeof(ICallHandler), 
                    typeof(LogCallHandler), "MyCallHandler");
        this.RegisterType(typeof(IMatchingRule), 
                       typeof(AnyMatchingRule), "AnyMatchingRule");

        this.RegisterType<IMyClass, MyClass>();
    }
    //apparently there is a new way to do this part
    // http://msdn.microsoft.com/en-us/library/ff660911%28PandP.20%29.aspx

    public void SetupForInteception(Type t)
    {
        this.Configure<Interception>()
        .SetInterceptorFor(t, new InterfaceInterceptor())
        .AddPolicy("LoggingPolicy")
        .AddMatchingRule("AnyMatchingRule")
        .AddCallHandler("MyCallHandler");

    }
}
//THIS will match which methods to log.
public class AnyMatchingRule : IMatchingRule
{
    public bool Matches(MethodBase member)
    {
        return true;//this ends up loggin ALL methods.
    }
}
public class LogCallHandler : ICallHandler
{
    public IMethodReturn 
             Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
      //All method calls will result in a call here FIRST.
      //IMethodInvocation has an exception property which will let you know
      //if an exception occurred during the method call.
    }
 }

回答by Alois Kraus

Use a Profiler in tracing mode. Then you will see how everything does call each other and where the time is spent. Besides commercial profilers there are also free ones. For managed code there is NP Profilerwhich is quite good.

在跟踪模式下使用探查器。然后你会看到一切是如何相互调用的,以及时间花在哪里。除了商业分析器,还有免费的分析器。对于托管代码,有非常好的NP Profiler

If you want to go deeper you can use the Windows Performance Toolkitwhich gives you full information accross all threads and how the interact with each other if you want to know. The only difference is that you get stacks ranging from kernel until your managed frames.

如果您想更深入地了解,可以使用Windows Performance Toolkit,它为您提供所有线程的完整信息以及您想知道的如何相互交互。唯一的区别是您获得的堆栈范围从内核到托管帧。

If this is not enough you can instrument your code with a tracing library (either automatically with PostSharp, ....) or manually or with a macro for each source file. I have made a little tracing library which is quite fast and highly configurable. See here. As unique feature it can trace any thrown exception automatically.

如果这还不够,您可以使用跟踪库(自动使用 PostSharp,....)或手动或使用每个源文件的宏来检测您的代码。我制作了一个非常快速且高度可配置的小跟踪库。见这里。作为独特的功能,它可以自动跟踪任何抛出的异常。

private void SomeOtherMethod()
{
  using (Tracer t = new Tracer(myType, "SomeOtherMethod"))
  {
      FaultyMethod();
  }
}

private void FaultyMethod()
{
   throw new NotImplementedException("Hi this a fault");
}

Here comes the output:

这是输出:

    18:57:46.665  03064/05180 <{{         > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod  
    18:57:46.668  03064/05180 <{{         > ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod  
    18:57:46.670  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Exception thrown: System.NotImplementedException: Hi this a fault    
at ApiChange.IntegrationTests.Diagnostics.TracingTests.FaultyMethod()  
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod()  
at ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod()    
at ApiChange.IntegrationTests.Diagnostics.TracingTests.Demo_Show_Leaving_Trace_With_Exception() 

18:57:46.670  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeOtherMethod Duration 2ms 18:57:46.689  03064/05180 <         }}< ApiChange.IntegrationTests.Diagnostics.TracingTests.SomeMethod Duration 24ms

回答by Goran

PostSharp certainly offers a way to apply an aspect to several targets without decorating them with attributes explicitly. See Multicast attributes.

PostSharp 当然提供了一种将方面应用于多个目标的方法,而无需显式地用属性装饰它们。请参阅多播属性

When developing (multicast) aspect you must specify its usage:

在开发(多播)方面时,您必须指定其用法:

[MulticastAttributeUsage(MulticastTargets.Method, TargetMemberAttributes = MulticastAttributes.Instance)]
[AttributeUsage(AttributeTargets.Assembly|AttributeTargets.Class|AttributeTargets.Method, AllowMultiple = true)]
[Serializable]
public class TraceAttribute : MethodInterceptionAspect
{
// Details skipped.
}

And then apply the aspect in a way that covers your use case (eg. all public members in AdventureWorks.BusinessLayer namespace):

然后以涵盖您的用例的方式应用方面(例如 AdventureWorks.BusinessLayer 命名空间中的所有公共成员):

[assembly: Trace( AttributeTargetTypes="AdventureWorks.BusinessLayer.*", AttributeTargetMemberAttributes = MulticastAttributes.Public )]