2010-11-21 22 views
3

Je souhaite implémenter IOC dans mon application mais je suis confus. Dans mon application, j'ai plusieurs classes concrètes qui implémentent une interface. Considérez ce scénario: -Utilisation du conteneur IOC pour plusieurs types de béton

Je dispose d'un ICommand Inteface et suivants types concrets qui mettent en œuvre cette interface: -

  • AddAddress
  • AjoutContact
  • RemoveAddress
  • removeContact

Fondamentalement l'utilisateur effectue toute cette action dans l'interface utilisateur, puis la liste est transmise à la couche de service où La commande h est exécutée.

donc dans la couche graphique, je vais écrire

ICommand command1 = new AddAddress(); 
ICommand command2 = new RemoveContact(); 

Dans la commande mangeoire

List<ICommand> listOfCommands = List<ICommand>(); 
listOfCommands.Add(command1); 
listOfCommands.Add(command2); 

Puis, finalement, passera listOfCommands à la couche de service.

Maintenant, selon ma compréhension d'IOC, une seule classe concrète est mappée à l'interface. Et nous utilisons cette syntaxe pour obtenir notre type concret à partir du conteneur StructureMap.

ICommand command = ObjectFactory.GetInstance<ICommand>(); 

Comment devrais-je implémenter IOC dans ce scénario?

Répondre

0

La plupart des conteneurs IOC vous permettent d'enregistrer des «instances nommées» d'interfaces, ce qui vous permet d'enregistrer plusieurs implémentations de ICommand, chacune avec son propre nom unique. En StructureMap, vous les demander comme ceci:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress"); 

Jetez un oeil à this question pour voir comment vous configurer le conteneur dans StructureMap.

3

Dans ce scénario, vous êtes mieux de faire vos commandes en objets de valeur, à savoir pas créé par le conteneur IoC:

class AddAddressCommand { 
    public AddAddressCommand(string address) { 
     Address = address; 
    } 
    public string Address { get; private set; } 
} 

Lorsque vous créez une commande, vous ne voulez vraiment une implémentation spécifique, et vous voulez le paramétrer avec précision, les deux problèmes qui vont à l'encontre des services du conteneur IoC. Cela deviendra encore plus pertinent si vous décidez à un certain moment de sérialiser les objets de commande.

Au lieu de cela, faire les composants de la couche de service qui exécutent les commandes en composants fournis IoC:

Dans votre cas, le composant qui accepte la liste des commandes à exécuter devront résoudre le gestionnaire approprié pour chaque commande et l'envoi de l'objet commande. Voici une discussion sur la façon de faire avec Windsor ici: http://devlicious.com/blogs/krzysztof_kozmic/archive/2010/03/11/advanced-castle-windsor-generic-typed-factories-auto-release-and-more.aspx - la communauté supportant votre conteneur IoC de choix sera en mesure de vous aider avec sa configuration.

1

Comme mentionné par Mark, StructureMap vous permettra de configurer et d'appeler les instances nommées d'une interface:

ObjectFactory.Initialize(x => 
{ 
    x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName"); 
} 

Vous pouvez toujours ajouter une instance par défaut pour cette interface particulière, bien sûr:

ObjectFactory.Initialize(x => 
{ 
    x.For<ISomeInterface>().Add<DefaultImplementation>();  
    x.For<ISomeInterface>().Add<SomeImplementation>().Named("SomeName"); 
} 

Lorsque vous appelez ObjectFactory.GetInstance<ISomeInterface>(); l'instance par défaut (celle initialisée avec Use au lieu de Add) est celle qui sera retournée.

Donc, dans votre cas, la mise en place ressemblerait à quelque chose comme:

ObjectFactory.Initialize(x => 
{ 
    // names are arbitrary 
    x.For<ICommand>().Add<AddAddress>().Named("AddAddress"); 
    x.For<ICommand>().Add<RemoveContact>().Named("RemoveContact"); 
} 

Ceux-ci seraient appelés comme l'a souligné Mark:

ObjectFactory.GetNamedInstance<ICommand>("AddAddress"); 
ObjectFactory.GetNamedInstance<ICommand>("RemoveContact"); 

Hope this helps.