venerdì 1 ottobre 2010

Unity - Microsoft Patterns & Practices

Dopo aver introdotto nel post precedente la Dependency Injection vorrei mostrarvi come utilizzare questo pattern nei vostri progetti in ambiente .NET.
La Microsoft mette a disposizione una libreria molto utile a riguardo: Unity.
Dopo aver scaricato e installato unity 2.0 siamo pronti ad utilizzarlo. Vediamo come fare nel classico caso di una applicazione web in ASP.NET.
  1. Aggiungere i riferimenti alle seguenti dll: Microsoft.Practices.Unity.dll e Microsoft.Practices.Unity.Configuration.dll
  2. Istruire il web.config della presenza di una nuova sezione dedicata a Unity:
    <configSections>
        ...
        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
    </configSections>
  3. Aggiungere poi la sezione relativa a Unity nel web.config
    <unity>
        <containers>
            <container>
                <types>
                    <type type="WebSite.Model.MyInterface,
    WebSite.Model" mapTo="WebSite.Model.MyImplementation">
                    </type>
                </types>
            </container>
        </containers>
    </unity>

    E' proprio nel file xml di configurazione (web.config) che istruiamo Unity su come risolvere le nostre dipendenze. In pratica in questo esempio stiamo mappando (mapTo) i riferimenti all'interfaccia MyInterface con la classe MyImplementation. Entrambe queste classi sono definite nella dll WebSite.Model. Questi nomi dovranno evidentemente essere sostituiti con classi e interfacce reali del vostro progetto. Notiamo inoltre che in questo esempio stiamo mostrando la configurazione minima (mapping di una interfaccia con una classe) ma la libreria prevede altre interessanti possibilità di configurazione.
  4. In un progetto web è utile inserire il container di Unity nell'oggetto "Application" (System.Web.HttpApplicationState) per la richiesta Web corrente attraverso il file Global.asax:
    <%@ Application Language="C#" %>
    <%@ Import Namespace="Microsoft.Practices.Unity" %>
    <%@ Import Namespace="Microsoft.Practices.Unity.Configuration" %>

    <script RunAt="server">
        void Application_Start(object sender, EventArgs e)
        {
            // create and populate a new Unity container from configuration
            var container = new UnityContainer();
            var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Configure(container);
            Application["Container"] = container;
        }

        void Application_End(object sender, EventArgs e)
        {
            //  Codice eseguito all\'arresto dell'applicazione
            Application["Container"] = null;
        }
       
        ...
    </script>
  5. A questo punto non ci resta che utilizzare l'interfaccia MyInterface lasciando il compito al container di Unity di risolvere la "Dependency". Nel code behind di una pagina aspx avremo qualcosa del tipo:
    ...
    private MyInterface _esempio;


    protected void Page_Load(object sender, EventArgs e)

    {

        _
    esempio = (Application["Container"] as IUnityContainer).Resolve<MyInterface>();
    }

    ...

    Potremo utilizzare così i metodi di MyInterface senza proccuparci di inizializzare la reference con un classe specifica: c'è Unity che lo fa per noi utilizzando le informazioni del web.config!
Prima di completare il post vorrei solo mostrarvi come dire a Unity che le nostre dependency devono essere risolte con un singolo oggetto per tipo. In pratica se vogliamo che le istanze siano dei Singleton basta aggiungere il seguente tag:
   <lifetime type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
    Microsoft.Practices.Unity" /> 
All'interno del tag "type" contenente il mapping che vogliamo tradurre con un Singleton.

    2 commenti:

    Pauletto ha detto...

    Molto buon supporto. Io lo proverò.

    Paolo Mosca ha detto...

    Grazie Pauletto e a presto

    Posta un commento