2009-10-27 3 views
0

J'ai une configuration structuremap qui me gratte la tête. J'ai une classe concrète qui nécessite un élément d'interface utilisateur interfacé qui nécessite une classe de validation interfacée. Je veux que la classe concrète externe obtienne l'élément d'interface utilisateur par défaut, mais obtienne un objet de validation spécifique à la classe concrète. Quelque chose comme ceci:Définir la dépendance interne par type en utilisant Structuremap

class MyView 
{ 
    IPrompt prompt 
} 

class GenericPrompt : IPrompt 
{ 
    IValidator validator 
} 

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

Comment puis-je configurer StructureMap avec le DSL de Registre pour utiliser uniquement MyValidator lors de la création de dépendances pour MyView. (Et supposément en utilisant BobsValidator lors de la création de dépendances pour BobsView)

+0

Est-ce que BobsView a aussi une dépendance à IPrompt? Sinon, vous n'avez aucun problème. Si oui, vous pourriez vouloir regarder dans les profils. – KevM

Répondre

1

Obtenez-vous MyView (et BobsView) à partir du conteneur? Pouvons-nous supposer qu'ils prendront tous une instance d'IPrompt? Une approche consisterait à enregistrer tous vos valideurs avec un nom correspondant aux noms de votre vue. Vous pouvez mettre en œuvre votre propre scanner de type qui supprime tout 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 assumez une IPrompt sera toujours demandée par une vue qui suit cette convention de nommage, votre registre pourrait ressembler à:

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 point de vue avec le validateur approprié, vous devez demander le type de béton:

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

Notez que cela ne fonctionnera que si vous êtes rEtri Eving votre vue avec un appel direct au conteneur (emplacement du service), car il dépend de la "Root.RequestedType". En fonction de la façon dont vous envisagez d'obtenir vos vues, vous pourriez être en mesure de parcourir le BuildStack à la recherche d'une vue (au lieu de supposer que c'est toujours Root).

+0

Merci. Cela m'a juste ce dont j'avais besoin. Toute idée de pourquoi l'intellisense sur ctx ne semble pas fonctionner? – JoshRivers

Questions connexes