2013-02-13 8 views
18

Ich habe ein bestehendes Projekt, wo ich herausfinden möchte, alle Anrufe gemacht und vielleicht in eine Protokolldatei dump.Wie verfolgen Sie jede Methode namens

Ich hatte einen Blick at this thread, aber half nicht viel. Ich habe PostSharp versucht, und das Beispiel zeigt, wie man es erreicht. Aber ich muss jeder Darn-Methode ein Attribut hinzufügen. Als ein bestehendes Projekt mit zahlreichen Methoden ist das keine machbare Option.

Gibt es andere Mittel, mit denen ich alle Anrufe schnell verfolgen kann?

+0

Haben Sie einen Blick nahm http://stackoverflow.com/questions/171970/how-can-i-find-the-method-that-called-the-current-method –

+0

ich nicht helfen kann aber wundere dich, warum du das willst. Im Falle einer Ausnahme können Sie den StackTrace anzeigen. Aber warum sollten Sie ein Protokoll aller Methodenaufrufe haben wollen? – comecme

+0

Es gibt einen Fehler, den wir bis zu einem bestimmten Punkt verfolgen können, und danach geht das Steuerelement zur übergeordneten App, die nicht unsere Anwendung ist - also kein Quellcode (irgendwo danach reagiert die App nicht mehr). Um herauszufinden, was in unserer App danach aufgerufen wird, versuchen wir dies. –

Antwort

9

Sie können dies tun, mit Unity Interception

dieses article for a sample See. Der Artikel verwendet Attribute, aber mein Codebeispiel unten verwendet das Abhängigkeits-Injektionssystem (das für eine Schnittstelle codiert), um das Abfangen einzurichten.

Wenn Sie MyClass anmelden wollen, ist es etwas geht:

  1. eine Schnittstelle machen, dass IMyClass
  2. Sie Setup InterfaceInterception in MyClass => alle Methoden enthält (wie ich habe unten getan) OR Es gibt ein paar andere Möglichkeiten, wie Sie es einrichten können. Siehe here for all options.
  3. Sie richten eine Richtlinie zum Abfangen aller Methoden ein, die mit IMatchingRule übereinstimmen. Alle Anrufe werden jetzt von Ihrer ICallHandler Implementierung abgefangen.

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. 
    } 
} 
+0

Ich denke, er versucht, das zu tun, ohne ein Attribut zu jedem hinzuzufügen Methode/Klasse (die sich vom Beispiel unterscheidet) – eyossi

+0

Aber mein Code benötigt keine Attribute. – gideon

+0

Klingt so, als müssten Sie für jede Klasse eine Schnittstelle erstellen; das ist meiner Meinung nach mehr Arbeit als Attribute. –

4

einen Profiler Verwenden Sie im Modus verfolgen. Dann wirst du sehen, wie sich alles anruft und wo die Zeit verbracht wird. Neben kommerziellen Profilern gibt es auch kostenlose. Für verwalteten Code gibt es NP Profiler, die ziemlich gut ist.

Wenn Sie tiefer gehen möchten, können Sie die Windows Performance Toolkit verwenden, die Ihnen vollständige Informationen über alle Threads gibt und wie die miteinander interagieren, wenn Sie wissen wollen. Der einzige Unterschied besteht darin, dass Sie Stacks vom Kernel bis zu den verwalteten Frames erhalten.

Wenn das nicht genug ist, können Sie Ihren Code mit einer Tracing-Bibliothek (entweder automatisch mit PostSharp, ....) oder manuell oder mit einem Makro für jede Quelldatei instrumentieren. Ich habe eine kleine Tracing-Bibliothek erstellt, die ziemlich schnell und in hohem Maße konfigurierbar ist. Siehe here. Als einzigartiges Feature kann es jede ausgelöste Ausnahme automatisch verfolgen.

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

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

Hier kommt die Ausgabe:

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 
5

Postsharp bietet sicherlich eine Möglichkeit, einen Aspekt auf mehrere Ziele anzuwenden, ohne sie mit Attributen explizit zu dekorieren. Siehe Multicast attributes.

Wenn (Multicast) Aspekt der Entwicklung müssen Sie dessen Nutzung festlegen:

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

Und dann den Aspekt in einer Weise anwenden, die Ihren Anwendungsfall deckt (zB alle öffentlichen Mitglieder in AdventureWorks.BusinessLayer Namespace.):

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