2013-09-02 5 views
13

Ich versuche einige Probleme in einer Legacy-Code-Basis zu debuggen. Ich denke, dass eine Ausnahme ausgelöst wird, weil etwas nicht aus dem Autofac-Container gelöst werden kann. Aber ich denke, die Ausnahme wird irgendwo vergraben und ich sehe die Ursache nicht. Ich bin mir sicher, dass etwas von einem Controller angefordert wird, der entweder nicht gefunden werden kann oder etwas, das gefunden werden kann, hat eine Abhängigkeit, die nicht erfüllt werden kann. Es gibt keine Wächterklauseln usw. Ich denke, ich bekomme ein Null-Referenz-Problem. Um dies zu testen, möchte ich alle Anfragen sehen, die nicht im Container gefunden werden.Wie kann ich alle Auflösungsanforderungen in den Autofac-Container protokollieren?

Gibt es trotzdem eine Protokollierung aller Anfragen, die Autofac nicht lösen konnte? Oder alternativ einfach alle Anfragen an den Container protokollieren?

Antwort

30

Sie können für Anfragen an den Container-Protokollierung hinzufügen, indem Sie ein spezielles Modul Registrierung, die das Preparing Ereignis für alle Registrierungen fangen:

public class LogRequestsModule : Module 
{ 
    protected override void AttachToComponentRegistration(
    IComponentRegistry componentRegistry, 
    IComponentRegistration registration) 
    { 
    // Use the event args to log detailed info 
    registration.Preparing += (sender, args) => 
     Console.WriteLine(
     "Resolving concrete type {0}", 
     args.Component.Activator.LimitType); 
    } 
} 

Dies ist der einfachste Weg zu gehen und werden Sie wahrscheinlich bekommen, was Sie wollen . Direkt nachdem ein Ereignis Preparing die Informationen protokolliert, wird die Ausnahme angezeigt und Sie wissen, welche Komponente ausgelöst wurde.

Wenn Sie schicker erhalten möchten, können Sie einige Event-Handler auf dem Behälter ChildLifetimeScopeBeginning, ResolveOperationBeginning, ResolveOperationEnding und CurrentScopeEnding Ereignisse einrichten.

  • Während ChildLifetimeScopeBeginning würden Sie brauchen, um etwas einzurichten, um automatisch auf jedes Kind Lebensdauer ResolveOperationBeginning Ereignisse anhängen.
  • Während ResolveOperationBeginning würden Sie protokollieren, was gelöst werden soll.
  • Während ResolveOperationEnding würden Sie alle Ausnahmen melden, die herauskommen.
  • Während CurrentScopeEnding müssen Sie sich von allen Ereignissen in diesem Bereich abmelden, damit der Garbage Collector den Gültigkeitsbereich der Lebensdauer mit allen Instanzen bereinigen kann.

The Whitebox profiler project has a module, dass einige dieser erweiterten Protokollierung implementiert, aber es ist nicht für die neueste Autofac eingerichtet, so dass Sie es als Ausgangspunkt verwendet werden müßten, kein Ausschneiden/Einfügen Probe.

Noch einmal, die einfachste Lösung ist, dass Modul ich oben gepostet.

+5

Ich weiß, SO runzelt die Stirn auf Dank. Ich schätze jedoch die Bemühungen, die Sie zur Unterstützung von Autofac-Fragen unternommen haben. Antworten sind immer sehr detailliert – GraemeMiller

+0

Nur für weniger Abhängigkeit injiziert, wie ich, das ist, wie Sie dieses Modul registrieren: builder.RegisterModule (); –

+0

Travis danke für die Antwort, Könnten Sie bitte einen Ausschnitt zeigen, wie man den Scope-Namen des aufgelösten Typs protokolliert? –

19

Nur um auf eine ausgezeichnete Antwort von Travis aufzubauen, falls es jemandem in Zukunft hilft.

Wenn Ihre Klassenstruktur sehr tief ist, ist es möglicherweise einfacher, den problematischen Pfad zu erkennen, wenn Sie Objekte in einer Kompositionshierarchie anzeigen. Dies kann mit somehting wie dies erreicht werden:

using System; 
using System.Text; 
using Autofac; 
using Autofac.Core; 

namespace Tests 
{ 
    public class LogRequestModule : Module 
    { 
     public int depth = 0; 

     protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, 
                   IComponentRegistration registration) 
     { 
      registration.Preparing += RegistrationOnPreparing; 
      registration.Activating += RegistrationOnActivating; 
      base.AttachToComponentRegistration(componentRegistry, registration); 
     } 

     private string GetPrefix() 
     { 
      return new string('-', depth * 2); 
     } 

     private void RegistrationOnPreparing(object sender, PreparingEventArgs preparingEventArgs) 
     { 
      Console.WriteLine("{0}Resolving {1}", GetPrefix(), preparingEventArgs.Component.Activator.LimitType); 
      depth++; 
     } 

     private void RegistrationOnActivating(object sender, ActivatingEventArgs<object> activatingEventArgs) 
     { 
      depth--;  
      Console.WriteLine("{0}Activating {1}", GetPrefix(), activatingEventArgs.Component.Activator.LimitType); 
     } 
    } 
} 

Beispielausgabe:

--Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapter 
----Resolving SomeProject.Web.Integration.RestApiAdapter.Client.ClientFactory 
------Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration 
------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration 
------Resolving SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService 
--------Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration 
--------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration 
------Activating SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService 
+1

GetPrefix() kann eine neue Zeichenfolge ('-', _depth * 2) zurückgeben; – angularsen

+0

Guter Vorschlag, implementiert, ich war ein bisschen zu ausführlich –

+1

Nitpicking, aber sicherlich 'Tiefe' sollte eine Instanz Eigenschaft sein, nicht statisch. Chancen von je zwei gleichzeitig verwenden sind eindeutig entfernt, aber immer noch ... – piers7