Michel Perfetti
Découverte de Unity
Unity est un « application block » dédié à l’injection de dépendances fournit par Microsoft. Dans cet article nous verrons comment l’utiliser pour limiter le couplage de nos applications
Par Michel Perfetti publié le 26/07/2009 à 22:57, lu 2867 fois, 5 pages
 4 | Utilisation de Unity
La première étape de l’utilisation de Unity est sa configuration. Pour cet article je vais me limiter à la configuration par code, mais la configuration par fichier de configuration est tout aussi simple. Avant de configurer il faut expliquer un peu comment Unity fonctionne. Unity contient une classe spéciale le « UnityContainer ». C’est elle qui va contenir les dépendances. Ce conteneur va permettre ensuite de résoudre ces dépendances par les couches applicatives.
Commençons par référencer l’assembly de Unity «  Microsoft.Practices.Unity » dans l’application.
Ensuite dans la fenêtre de l’application je vais créer un conteneur, et le configurer avec les couches de données et logiques :

IUnityContainer _unityContainer;

 

public Form1()

{

    InitializeComponent();

    _unityContainer = new UnityContainer();

 

    _unityContainer.RegisterType<ICustomerDataAccess, CustomerDataAccess>();

    _unityContainer.RegisterType<ICustomerLogicLayer, CustomerLogic>();

}

Dans ce cas Unity aura la charge d’instancier les classes qui correspondent aux interfaces. Il est possible de dire à Unity comment doit se faire l’instanciation : à chaque résolution, un par thread, une seule instance (Singleton) …
Il est aussi possible de passer à Unity une instance qui correspond à une interface :

_unityContainer.RegisterInstance<ICustomerDataAccess>(new CustomerDataAccess());

Attaquons la résolution. Il suffit de remplacer le code suivant :

var logic = new LogicLayer.CustomerLogic(new DataLayer.CustomerDataAccess());

Par celui-ci :

var logic = _unityContainer.Resolve<ICustomerLogicLayer>();

Notre code (sans parler de la configuration) n’a plus aucune connaissance des couches utilisées, mais juste des interfaces !
Comment Unity a-t-il pu créer la classe CustomerLogic alors que le constructeur avait besoin d’un paramètre ? C’est simple : grâce aux dépendances enregistrées dans le conteneur. Revenons au constructeur de la couche logique :

public CustomerLogic(ICustomerDataAccess dataLayer)

{

    _dataLayer = dataLayer;

}

ICustomerDataAccess est une interface résolue dans le conteneur. Unity a donc résolu ce paramètre à la volée lors de la création de la classe !
Unity est assez intelligent pour se considérer lui-même comme une sorte de dépendance : il existe une interface IUnityContainer qui permet de résoudre le conteneur courant. Imaginons que je ne souhaite plus avoir l’interface de la couche de donnée dans mon constructeur de la couche logique mais directement le conteneur Unity. Il suffit de modifier le code de cette façon :

public class CustomerLogic: ICustomerLogicLayer

{

    IUnityContainer _unityContainer;

 

    public CustomerLogic(IUnityContainer container)

{

    _unityContainer = container;

}

 

    public Customer Create(string customerName, string companyName)

    {          

        var id = Guid.NewGuid().ToString("N").Substring(0, 5).ToUpper();

        var dataLayer = _unityContainer.Resolve<ICustomerDataAccess>();

        return dataLayer.Insert(id, customerName, companyName);

    }

 

    public List<Customer> GetAllCustomers()

    {

        var dataLayer = _unityContainer.Resolve<ICustomerDataAccess>();

        return dataLayer.GetAllCustomer().OrderBy(cust => cust.ContactName).ToList();

    }

}

La puissance d’utilisation des conteneurs d’injection de dépendance est là : dans nos couches, il n’est plus nécessaire d’avoir des liens vers les couches que l’on veut utiliser, mais seulement sur les contrats d’interfaces qui leur correspond, en récupérant le conteneur via le constructeur on peut développer sans se soucier des autres bibliothèques.
Unity possède d’autres moyens pour injecter des dépendances dans les classes au moment de leur instanciation. En particulier il est aussi possible de passer par une propriété publique (elle est marquée par l’attribut « Dependency ») :

public class CustomerLogic: ICustomerLogicLayer

{

    [Dependency]

    public IUnityContainer UnityContainer { get; set; }

 

    public CustomerLogic()

    {

    }

 

    public Customer Create(string customerName, string companyName)

    {          

        var id = Guid.NewGuid().ToString("N").Substring(0, 5).ToUpper();

        var dataLayer = UnityContainer.Resolve<ICustomerDataAccess>();

        return dataLayer.Insert(id, customerName, companyName);

    }

 

    public List<Customer> GetAllCustomers()

    {

        var dataLayer = UnityContainer.Resolve<ICustomerDataAccess>();

        return dataLayer.GetAllCustomer().OrderBy(cust => cust.ContactName).ToList();

    }

}

Unity permet aussi via la méthode « BuildUp » du conteneur de résoudre des dépendances dans une classe existante.
 
» Démarrer une discussion
 
Discussion démarée par stiiifff le 29/07/2009 à 02:33, 1 commentaire(s).