26/06/11

Utilizzare Windsor IOC container con l'autoregistration

Castle Windsor è una libreria che pemette di iniettare automaticamente le dipendenze all'interno di una nostra classe (Dipendency Injection).

Questo significa che se abbiamo una classe con un costruttore che accetta come parametro delle interfacce, sostanzialmente non dovremo essere noi a fare il "new" della classe che implementa quella interfaccia, ma verrà fatto in automatico dalla libreria.

Questo è un esempio di una classe che ha nel costruttore una interfaccia di nome IRepository

public class SendMailTask : ISendMailTask
    {
        private IRepository2 _repository2;

        public SendMailTask(IRepository2 repository2)
        {
            _repository2 = repository2;
        }
    }

Normalmente per instanziare la nostra classe SendMailTask dovremmo scrivere:

SendMailTask sendMailTask = new SendMailTask(new Repository2());


Utilizzando invece Windsor, potremo scrivere:


var sendMailTask = ServiceLocatorInitializer.Container.Resolve();

Come avrete notato non abbiamo passato noi a parametro l'instanza della classe richiesta, perchè viene fatto in automatico.

Risulta molto utile quando abbiamo più parametri nel costruttore, ma soprattutto ci facilita la possibilità di testare il codice attraverso gli Unit Test.


Come funziona

Come prima cosa effettuiaamo il download di Windsor Castle dal sito www.castleproject.org

Poi referenziamo nel nostro progetto le librerie CastleCore,CastleMicrokernel e CastleWindsor

A questo punto dobbiamo registrare le dipendenze in modo che il programma sappia in automatico quale componente (o classe)
è legato ad una determinata interfaccia
e in questo modo sappia quale instanza deve creare a runtime e iniettare nel costruttore della classe.

Possiamo utilizzare un file di configurazione che non spiegheremo in questo post e nel quale registriamo le dipendenze.




    
        
        

        

        

        

    





Oppure possiamo utilizzare una nuova caratteristica di Windsor che si chiama AutoRegistration e permette
in automatico di registrare le dipendenze di uno o più assembly.

Ecco un esempio completo:

_container = new WindsorContainer();


            _container.Register(
                        AllTypes.Pick()
                        .FromAssemblyNamed(Assembly.GetExecutingAssembly().FullName)
                        .WithService.FirstInterface());


Ecco fatto, in questo modo vengono registrate tutte le dipendenze interfaccia/classe dell'assembly corrente.
Possiamo anche decidere di aggiungere altre dipendenze manualmente:


container.AddComponent("entityDuplicateChecker",
                typeof(IEntityDuplicateChecker), typeof(EntityDuplicateChecker));

Ora possiamo instanziare le nostre classi in questo modo:
var sendMailTask = ServiceLocatorInitializer.Container.Resolve();


Se abbiamo la necessità di utilizzare Windsor in varie classi, non dobbiamo instanziarlo ogni volta ma semplicemente
faremo una classe di helper usando il pattern Singleton; la prima volta chiameremo il metodo Init, le volte successive essendo una classe statica
potremo semplicemente utilizzare la proprietà pubblica "Container"

public class ServiceLocatorInitializer
    {
        private static IWindsorContainer _container;

        public static IWindsorContainer Container
        {
            get { return _container; }
        }

        public static void Init()
        {
            _container = new WindsorContainer();

            ComponentRegistrar.AddComponentsTo(_container);
            _container.Register(
                        AllTypes.Pick()
                        .FromAssemblyNamed(Assembly.GetExecutingAssembly().FullName)
                        .WithService.FirstInterface());
         
        }
    }

0 commenti:

Posta un commento

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Grants For Single Moms