2

Est-il possible d'utiliser RegisterConditional sans spécifier les types d'implémentation (similaire au fonctionnement de Register)? J'utilise Simple Injector pour câbler la validation courante de mon application CQRS/MVC. Jusqu'à présent, l'inscription validateurs (qui sont tous deux utilisés par MVC et par un pipeline décorateur de pile CQRS) a été simple:Enregistrement de génériques ouverts avec condition

container.Register(typeof(IValidator<>), assemblies, lifestyle); 

container.RegisterConditional(
    typeof(IValidator<>), 
    typeof(ValidateNothingDecorator<>), 
    Lifestyle.Singleton, 
    c => !c.Handled) 

Un nouveau moyen exigence que je dois mettre en œuvre quelque chose de similaire à valiators, mais des mises en garde. Je ne veux pas utiliser le "niveau d'erreur" intégré de Fluent Validation pour diverses raisons, ce qui signifie que je devrai créer des validateurs supplémentaires pour des types donnés, ce qui donnera bien sûr plusieurs enregistrements pour une seule erreur de vérification de type.

Ce que je voudrais faire est d'enregistrer tout ce qui met en œuvre IValidator<> sauf pour si elle met également en œuvre IProvideWarnings, mais je ne veux pas énumérer chaque classe pour enregistrer

public class MyCommand : IDefineCommand {...} 
public class ValidateMyCommand : IValidator<MyCommand> {...} 
public class ProvideWarningsForMyCommand : IValidator<MyCommand>, IProvideWarnings {...} 
... 
// would like something like... (this obviously does not work) 
container.RegisterConditional(
    typeof(IValidator<>), 
    assemblies, 
    lifestyle, 
    c => !c.ImplementationType.GetInterfaces().Contains(typeof(IProvideWarnings))); 

Ma position de repli est de trouver tous les types que mettre en œuvre IValidator<> mais pas IProvideWarnings et passer cela en Register, cependant, je préfère le faire avec un prédicat dans l'appel d'enregistrement qu'une recherche différente.

Merci

Répondre

1

Comme vous l'avez déjà remarqué, Injector simple contient une surcharge de Register cela permet de fournir une liste de types à enregistrer. Alors que vous pouvez réfléchir vous-même sur l'assemblage, Simple Injector contient une méthode pratique qui fonctionne pour vous. Ce GetTypesToRegister filtrera automatiquement à la fois les décorateurs et les définitions de types génériques pour vous.

L'inscription suivante fera l'affaire:

var validatorTypes = 
    container.GetTypesToRegister(typeof(IValidator<>)) 
     .Where(typeof(IProvideWarnings).IsAssignableFrom); 

container.Register(typeof(IValidator<>), validatorTypes, lifestyle); 
+0

merci, c'est beaucoup plus propre que mon code, et je n'étais pas au courant (ou du moins, je n'avais pas lu assez profondément pour réaliser l'utilisation) de 'GetTypesToRegister'. Je vais utiliser ça! – AndrewP

1

Ma méthode pour résoudre ce problème consistait à utiliser ma position de repli.

Ayant à l'esprit il y a une des méthodes non standard dans le code ci-dessous (mais devrait être droite en avant assez), il ressemble à:

var validatorTypes = assemblies.SelectMany(a => a.GetTypes().Where(t => 
      t.IsClass && !t.IsAbstract && t.IsPublic && 
      t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IValidator<>)) && 
      !t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IProvideWarnings<>)) 
     )).ToList(); 

IocContainer.Register(typeof(IValidator<>), validatorTypes, IocContainer.DefaultLifestyle); 

IocContainer.RegisterConditional(typeof(IValidator<>), typeof(ValidateNothingDecorator<>), Lifestyle.Singleton, c => !c.Handled && !c.ServiceType.DoesImplement(typeof(IProvideWarnings))); 
+0

Votre ValidateNothingDecorator est en fait pas un décorateur, mais un objet nul. – Steven