0 votes

Définir la dépendance interne par type à l'aide de Structuremap

J'ai une configuration de structuremap qui me laisse perplexe. J'ai une classe concrète qui nécessite un élément ui interfacé qui nécessite une classe de validation interfacée. Je veux que la classe concrète extérieure obtienne l'élément ui par défaut, mais obtienne un objet de validation spécifique à la classe concrète. Quelque chose comme ceci :

class MyView 
{
   IPrompt prompt
}

class GenericPrompt : IPrompt
{
   IValidator validator
}

class MyValidator : IValidator
{
   bool Validate() {}
}

Comment puis-je configurer structuremap avec le Registry DSL pour n'utiliser que MyValidator lors de la création de dépendances pour MyView. (Et en supposant qu'il utilise BobsValidator lors de la création de dépendances pour BobsView).

1voto

Joshua Flanagan Points 5907

Obtenez-vous MyView (et BobsView) à partir du conteneur ? Pouvons-nous supposer qu'ils prendront tous une instance de IPrompt ?

Une approche consisterait à enregistrer tous vos validateurs avec un nom correspondant aux noms de vos vues. Vous pouvez implémenter votre propre analyseur de type qui supprime simplement le suffixe Validator :

public class ValidatorScanner : ITypeScanner
{
    public void Process(Type type, PluginGraph graph)
    {
        if (!typeof (IValidator).IsAssignableFrom(type)) return;
        var validatorName = type.Name.Replace("Validator", "");
        graph.AddType(typeof(IValidator), type, validatorName);
    }
}

Maintenant, si vous supposez qu'un IPrompt sera toujours demandé par une vue qui suit cette convention de nommage, votre registre pourrait ressembler à ceci :

public class ValidatorRegistry : Registry
{
    public ValidatorRegistry()
    {
        Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.With<ValidatorScanner>();
        });

        ForRequestedType<IPrompt>().TheDefault.Is.ConstructedBy(ctx =>
        {
            var viewName = ctx.Root.RequestedType.Name.Replace("View", "");
            ctx.RegisterDefault(typeof(IValidator), ctx.GetInstance<IValidator>(viewName));
            return ctx.GetInstance<GenericPrompt>();
        });
    }
}

Pour récupérer votre vue avec le validateur approprié, vous devez demander le type concret :

var view = container.GetInstance<MyView>();

Notez que cela ne fonctionnera que si vous récupérez votre vue par un appel direct au conteneur (emplacement du service), puisque cela dépend du "Root.RequestedType". Selon la façon dont vous prévoyez d'obtenir vos vues, vous pourriez être en mesure de remonter la BuildStack à la recherche d'une vue (au lieu de supposer qu'il s'agit toujours de Root).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X