1

Je construis des services de base pour les grandes applications et nous sommes passés de castle windsor à autofac. Tout fonctionne bien dans l'approche d'enregistrement automatique en utilisant la numérisation et les modules, mais nous avons un cas intéressant: il y avait 2 implémentations d'une interface et autofac les enregistrait bien sûr dans un ordre aléatoire qu'une mauvaise implémentation était résolue du point de vue commercial. Bien sûr, l'enregistrement manuel fait le travail mais il serait bien d'avoir une validation sur le niveau IContainer pour au moins donner des informations de sortie sur chaque service enregistré et s'il a plus d'une implémentation, il devrait les marquer par défaut - ce qui sera résolu lors de la demande de conteneur en utilisant la résolution. Le but est de forcer les développeurs à enregistrer une implémentation concrète spécifique quand il y a des multiples disponibles mais maintenir l'enregistrement automatique.
Avez-vous trouvé un moyen de ce cas?validation des enregistrements Autofac

+0

Aujourd'hui j'ai demandé même queation les développeurs GitHub qui maintient le code, mais la réponse est « il ne sera pas inclus dans api de base, car il aura un impact pour tant de classes de base » :(donc il est un indice pour vous – Macko

+0

Faire ce qu'il faut faire, tant que vous comprenez que l'information que vous sortez peut ou peut ne pas être exacte pour une solution simple: l'utilisation de la réflexion et l'accès aux structures et champs privés et autres. les raisons décrites dans [Autofac numéro 853] (https://github.com/autofac/Autofac/issues/853) –

+0

Merci Travis, j'ai déjà préparé une méthode d'extension agréable et facile à IContainer qui compte simplement les enregistrements et pour les inscriptions simples, il semble que ça fonctionne, je vais laisser mon code w ork pendant un moment et voir s'il gère des enregistrements plus complexes. – Macko

Répondre

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; 
    } 

}