2014-09-15 2 views
2

Je travaille avec IoC et plus précisément avec windsor et j'ai un doute amletic sur une chose. En ce moment, j'applique la couche de commande DDD donc pour chaque commande j'ai une classe concrète comme suitIoC éviter d'injecter le conteneur

public class CreateUserCommand : IDomainCommand{ 
    /// implementation 
} 

Chaque commande a 1 ou plusieurs gestionnaires avec la mise en œuvre suivante

public class CreateUserHandler : IDomainCommandHandler<CreateUserCommand> 
{ 
    public void Handle(CreateUserCommand command) 
    { 
     /// implementation 
    } 
} 

Le problème se pose avec mon répartiteur de commandes. J'utilise le formulaire ci-dessous au moment

public class CommandDispatcher : ICommandDispatcher 
{ 
    private IWindsorContainer container; 

    public CommandDispatcher(IWindsorContainer container) 
    { 
     this.container = container; 
    } 

    public void Dispatch<T>(T command) 
    { 
     var commandHandler = container.Resolve<ICommandHandler<T>>(); 
    commandHandler.Handle(command); 

    } 
} 

Ce que je n'aime pas est la prise de conscience du distributeur sur le conteneur IoC, mais de la même manière que je ne sais pas comment je peux trier de résoudre les gestionnaires seulement quand j'en ai besoin. Shell J'injecte une fabrique de gestionnaires dans Dispatcher et l'utilise pour résoudre mes gestionnaires lors de l'exécution.

+2

Il existe une autre façon de le faire correctement. Vous devez utiliser [TypedFactory Facility.] (Http://docs.castleproject.org/Windsor.Typed-Factory-Facility-interface-based-factories.ashx) Il ne doit y avoir aucune référence au conteneur DI dans votre application, où que ce soit Les outils et motifs dont vous avez besoin sont décrits dans la documentation. –

Répondre

7

Je voudrais utiliser le typed factory facility pour créer une usine pour remplacer l'utilisation du conteneur. Conceptuellement, l'idée est la même, mais elle supprime la dépendance sur le conteneur.

L'usine (pas mise en œuvre, l'installation prend en charge que):

public interface ICommandHandlerFactory 
{ 
    ICommandHandler<T> Create<T>(); 
} 

Inscription:

// requires Castle.Facilities.TypedFactory namespace 
windsorContainer.AddFacility<TypedFactoryFacility>(); 

// AsFactory() is an extension method in the same namespace 
windsorContainer.Register(Component.For<ICommandHandlerFactory>().AsFactory()); 

Puis dans votre classe:

public class CommandDispatcher : ICommandDispatcher 
{ 
    private ICommandHandlerFactory commandHandlerFactory; 

    public CommandDispatcher(ICommandHandlerFactory commandHandlerFactory) 
    { 
     this.commandHandlerFactory = commandHandlerFactory; 
    } 

    public void Dispatch<T>(T command) 
    { 
     var commandHandler = commandHandlerFactory.Create<T>(); 
     commandHandler.Handle(command); 
    } 
} 
+0

C'est exactement ce que je cherchais mais je ne savais pas que vous pouviez créer une usine en utilisant les propriétés génériques totales Merci – Raffaeu

2

Il est bon pour l'infrastructure code qui fait partie de votre composition root pour prendre une dépendance sur le conteneur. Ceci n'est pas une implémentation du Service Locator anti-pattern, puisque le localisateur de service est environ role and not mechanics. En d'autres termes, tant que votre CommandDispatcher fait partie de la racine de la composition (et ne contient que l'infrastructure, pas de logique métier), il est acceptable de le laisser dépendre du conteneur.

+0

Merci pour la réponse Steven, c'était ma principale préoccupation, ne pas sauter dans l'anti-pattern du localisateur de service. – Raffaeu

Questions connexes