.NET / Unity : Récupérer un type parmi plusieurs implémentations

Une application est souvent séparée en plusieurs couches, chacune ayant une responsabilité bien définie :

  • Présentation
  • Accès aux données
  • Gestion des règles métiers

Afin d’avoir une application maintenable et testable il est nécessaire d’avoir un faible couplage entre les différentes briques de votre application.
Ce découplage passe par des interfaces qui vont définir le rôle de chaque brique et ce quelles sont capable de faire. Ainsi une brique ne sera pas dépendante d’une implémentation mais d’une interface. Par exemple, la couche présentation est liée via des interfaces à des services. Elle ne sait pas qui implémente ses services. La couche de présentation n’a pas de référence à une implémentation particulière des interfaces des services. On pourra ainsi facilement bouchonner (mock : renvoi de données de test) afin de tester plus facilement son application.

C’est la qu’intervient Unity.

Présentation de Unity

Unity est un conteneur d’injection de dépendances. Il fait partie des patterns & pratices de Microsoft. Unity va vous permettre de définir dans votre application qu’elle est la classe qui implémente une interface et va vous retourner pour vous une instance de cette classe.

La configuration de Unity peut se faire de 2 façons :

  • par code (via le méthode RegisterType)
  • par fichier xml

Je préconise de passer par un fichier XML qui lui permet de ne pas recompiler l’application.

Voici un exemple de configuration qui permet de définir qu’il faut utiliser la classe MonService lorsque l’on a besoin d’une interface IMonService.

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <containers>
      <container>
        <types>
          <!-- Business services -->
          <type type="MyInterfaces.IMonService,MyInterfaces" mapTo="MyServices.MonService, MyServices"></type>
        </types>
      </container>
    </containers>
</unity>

La résolution par code se fait via la méthode Resolve sur le conteneur :

myContainer.Resolve<MyInterfaces.IMonService>();

Implémentation multiples d’une interface

Dans certains cas, il est possible que vous ayez besoin de plusieurs implémentations d’une même interface. (exemple : communication avec des machines ayant un protocole différents. On va ainsi utiliser le design pattern Commande qui va nous permettre d’avoir une seule interface de communication. Les implémentations permettent de masquer les différences de protocoles).
Il est possible de différentier les implémentations d’une même interface en spécifiant lors de la configuration de Unity un nom via l’attribut name.

Configuration par xml

<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService1, MyServices" name="MonInterface1"></type>
<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService2, MyServices" name="MonInterface2"></type>
<type type="MyInterfaces.IMonService, MyInterfaces" mapTo="MyServices.MonService, MyServices" name="MonInterface3"></type>

Configuration par code

myContainer.RegisterType<MyInterfaces.IMonService, MyServices.MonService1>("MonInterface1" ) ;

La résolution se fera via le code suivant :

myContainer.Resolve<MyInterfaces.IMonService>("MonInterface1");

Liens

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *