1

Ich baue Kerndienste für große App und wir wechselte von Burg Windsor zu Autofac. Alles funktioniert gut in der automatischen Registrierung mit assemly Scan und Module, aber wir haben in letzter Zeit interessante Fall: Es gab 2 Implementierungen von einer Schnittstelle und Autofac natürlich registrieren sie in zufälliger Reihenfolge, dass falsche Implementierung aus betriebswirtschaftlicher Sicht gelöst wurde. Natürlich macht die manuelle Registrierung den Job, aber es wäre schön, eine Validierung auf IContainer-Ebene zu haben, um zumindest Informationen über jeden einzelnen registrierten Service auszugeben und wenn es mehr als eine Implementierung hat, sollte er sie als Standard markieren - was sein wird behoben, wenn Container mit Auflösung abgefragt wird. Der Zweck besteht darin, Entwickler zu zwingen, eine bestimmte konkrete Implementierung zu registrieren, wenn mehrere verfügbar sind, die automatische Registrierung jedoch beibehalten wird.
Haben Sie einen Weg zu diesem Fall gefunden?Autofac Registrierungen Validierung

+0

Heute fragte ich gleiche queation auf Github-Entwicklern, den Code, aber die Antwort ist „es wird nicht in der Basis api enthalten sein, weil es so viele Kernklassen Auswirkungen hat“, behauptet :(so gibt es einen Tipp für Sie und es gibt mindestens 2 Ansätze, um eine einfache Lösung zu erstellen: eine mit Reflektion und Zugriff auf private Strukturen und Felder und andere mit offiziellen API – Macko

+0

Tun Sie was zu tun, solange Sie verstehen, die Informationen, die Sie erhalten, kann oder kann nicht genau sein die Gründe, die in [Autofac-Ausgabe # 853] beschrieben sind (https://github.com/autofac/Autofac/issues/853). –

+0

Dank Travis, ich habe bereits eine schöne und einfache Erweiterungsmethode für IContainer vorbereitet, die Anmeldungen einfach zählen und Für einfache Registrierungen sieht es so aus, als ob es funktioniert. Ich lasse meinen Code w Ork für eine Weile und sehen, ob es komplexere Registrierungen verwaltet. – Macko

Antwort

0
public static class AutofacExtensions 
{ 
    /// <summary> 
    /// Checks if one implementation was chosen by developer for every interface 
    /// </summary> 
    /// <param name="container"></param> 
    public static void ValidateRegistrations(this IContainer container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException(nameof(container)); 
     } 

     var registrations = GetRegistrations(container); 
     Validate(registrations); 
    } 

    static void Validate(IDictionary<Type, IList<Type>> registrations) 
    { 
     foreach (var registration in registrations.OrderBy(x => x.Key.FullName)) 
     { 
      var unique = registration.Value.Distinct().Count(); 

      if (unique > 1) 
      { 
       var all = registration.Value.Count; 

       if (all <= unique) 
       { 
        var currentImplementations = registration.Value.Distinct().Select(x => x.FullName); 
        var aggregatedImplementations = string.Join(", ", currentImplementations); 

        throw new InvalidOperationException($"IoC/DI: for type '{registration.Key.FullName}' was not chose default implementation! Registered available implementations: {aggregatedImplementations}"); 
       } 
      } 
     } 
    } 

    static IDictionary<Type, IList<Type>> GetRegistrations(IContainer container) 
    { 
     var registrations = new Dictionary<Type, IList<Type>>(); 

     foreach (var registration in container.ComponentRegistry.Registrations) 
     { 
      foreach (var service in registration.Services.OfType<IServiceWithType>().Where(x => x.ServiceType.Namespace != null && x.ServiceType.Namespace.ToLowerInvariant().StartsWith("flb."))) 
      { 
       IList<Type> implementations; 

       if (!registrations.TryGetValue(service.ServiceType, out implementations)) 
       { 
        implementations = new List<Type>(); 
        registrations[service.ServiceType] = implementations; 
       } 

       implementations.Add(registration.Activator.LimitType); 

      } 
     } 

     return registrations; 
    } 

}