Seleziona una pagina

DependencyInjectionIn questo articolo parleremo della Dependency Injection, un pattern che consente di creare applicazioni flessibili e semplifica la fase di unit test.

Quando si approccia per la prima volta alla dependency injection può risultare un po’ ostico da capire ed inizialmente si ha l’impressione che questo pattern rallenti la scrittura del codice, ma così non è !

La dependency injection facilita la creazione di componenti detti “debolmente accoppiati”. Per componenti debolmente accoppiati si intende quando utilizziamo un componente del quale conosciamo i metodi e le proprietà ma non conosciamo la sua implementazione.

Uno dei grandi vantaggi nell’utilizzo della dependency injection è che siamo portati a dover scrivere dei componenti o classi che saranno poi facilmente testabili in fase di unit test.

Vediamo ora come poter scrivere il codice per utilizzare al meglio la dependency injection.

Ipotizziamo di dover scrivere del codice per inviare una email, avremo una classe provider con i metodi necessari per gestire l’invio, ma  non sapendo quale server utilizzare (OWA o smtp), come possiamo scrivere il nostro codice senza avere tutte le informazioni?

Possiamo iniziare definendo l’interfaccia del nostro provider in questo modo

    public interface IEMailProvider
    {
        bool SendEMail(List<string> to, List<string> cc, string subject, string body);
    }
  

Ora conosciamo il metodo con i parametri che dobbiamo invocare per inviare la mail. Procediamo creando la nostra classe Helper che utilizza l’interfaccia sopra definita per l’invio della mail.

    public class EMailHelper
    {
        IEMailProvider _emailProvider;
       
        public bool SendEMail(List<string> to, List<string> cc, string subject, string body)
        {
            return _emailProvider.SendEMail(to, cc, subject, body);
        }
    }
  

A questo punto dobbiamo fare in modo che chi utilizza la classe helper possa passare l’implementazione dell’interfaccia  IEmailProvider , il metodo più utilizzato è quello di dare la possibilità di passare l’implementazione tramite il costruttore, in questo modo:

    public class EMailHelper
    {
        IEMailProvider _emailProvider;
        public EMailHelper(IEMailProvider emailProvider)
        {
            _emailProvider = emailProvider;
        }

        public bool SendEMail(List<string> to, List<string> cc, string subject, string body)
        {
            return _emailProvider.SendEMail(to, cc, subject, body);
        }
    }
  

Quando l’implementazione della classe viene passato nel costruttore stiamo parlando di “Constructor Injection”, in alternativa possiamo utilizzate il “Method Injection” dove l’implementazione viene passata direttamente al metodo che stiamo per eseguire.

Ora siamo in grado di poter chiamare la nostra classe helper specificando quale deve essere il provider da utilizzare, che nel nostro caso sarà un provider per OWA

    [HttpPost]
    public bool SendEMail(List<string> to, List<string> cc, string subject, string body)
    {
        var emailHelper = new EMailHelper(new OWAEmailProvider());
        return emailHelper.SendEMail(to, cc, subject, body);
    }
  

Naturalmente la nostra classe OWAEmailProvider deve implementare l’interfaccia IEMailProvider

public class OWAEmailProvider : IEMailProvider { public bool SendEMail(List<string> to, List<string> cc, string subject, string body) { . . . . . . . } }

Tutto quello che abbiamo visto fino ad ora è molto interessante, ma quello che risalta subito all’occhio è che alla fine deve esserci un componente che è a conoscenza di questo legame tra Interfaccia e la sua implementazione, questa informazione è configurata all’interno di un “Contenitore” ,detto anche IoC Container (IoC è l’acronimo di Inversion Of Controll) o Dependency Injection Container.

Il container ha una duplice funzione; la prima quella di mettere a disposizione l’associazione Interfaccia/Classe tramite dei metodi di ricerca, la seconda quella di Activator  delle classi in modo da poter gestire Constructor Injection per tutte quelle classi che sono presenti nel container (da qui Inversion Of Controll ‘istanziazione delle classi la esegue direttamente il container non la classe utilizzatrice).

Andiamo a vedere nel dettaglio l’implementazione della dependency Injection all’interno di ASP.NET Core.

In ASP.NET Core tutte le classi registrate nel IoC Container vengono chiamate servizi.

Nel momento in cui decido di registrare una servizio all’interno del IoC dobbiamo decidere il LifeTime con cui lo andremo ad utilizzare, le opzioni che abbiamo a disposizione sono:

  • Singleton

    Il servizio viene creato la prima volta che viene chiamato e tutte le richieste successive viene utilizzata la stessa istanza

  • Transient

    Il servizio viene creato ad ogni chiamata

  • Scoped

    Il servizio viene creato ad ogni chiamata, ma l’istanza è condivisa all’interno della stessa request

Per configurare i servizi all’interno dell’IoC Container dobbiamo eseguire la configurazione nella classe StartUp del progetto e più nel dettaglio nel metodo ConfigureService, che nel nostro caso sarà:

public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddMvc();

services.AddSingleton<IEMailProvider, OWAEmailProvider>(); }

L’implementazione della Dependency Injection di Microsoft è integrata nell ASP.NET Mvc Core Framework, e la maggior parte degli oggetti del MVC vengono attivati dal container, questo ci permette di poter utilizzare sia il Constructor Injection sia il Method Injection direttamente sul Controller, TagHelper, Middleware ed altri oggetti.

Una volta registrato il provider per l’invio email possiamo modificare il nostro controller in questo modo

    public class EMailController : Controller
    {
        IEMailProvider _emailProvider;

        public EMailController(IEMailProvider emailProvider)
        {
            _emailProvider = emailProvider;
        }

        [HttpPost]
        public bool SendEMail(List<string> to, List<string> cc, string subject, string body)
        {
            return _emailProvider.SendEMail(to, cc, subject, body);
        }

    }
  

Fino ad ora abbiamo visto esempi di constructor injection, ma abbiamo detto che l’IoC Container ti permette di ricercare direttamente i servizi.

Per poter accedere direttamente all’IoC Container nella classe HTTPContext è presente la proprietà RequestService di tipo IServiceProvider ,di seguito un esempio di come utilizzarla:

[Route("api/EMail")]
public class EMailController : Controller { [HttpPost] public bool SendEmail(List<string> to, List<string> cc, string subject, string body) { IEMailProvider emailProvider = (IEMailProvider)this.HttpContext.RequestServices.GetService(typeof(IEMailProvider)); return emailProvider.SendEMail(to, cc, subject, body); } }

Attualmente oltre all’implementazione Microsoft di Dependency Injection è possibile utilizzare anche altri framework come AUTOFAC o Ninject, su internet si trova la documentazione necessaria per configurare il framework preferito senza grandi interventi.

In questo articolo abbiamo parlato del pattern Dependency Injection ed abbiamo visto tramite un esempio pratico come implementarlo in ASP.NET MVC Core.

Vi aspetto per il prossimo articolo dove vedremo come la Dependency Injection ci aiuta nel costruire componenti facilmente testabili e come usare XUnit e Moq per scrivere i nostri unit test.

Happy coding !!!

Altri Articoli

Benvenuto ASP.NET Core 1.0
views 0
Lo scorso 19 gennaio Scott Hanselman ha annunciato sul suo blog la scelta di modificare il nome della prossima versione di ASP.NET, nel giro di una an...
ASP.NET: Messagebox
views 0
Questo semplice script permette di visualizzare a video una messagebox:VB.NET Private Sub ShowMessageBox(ByVal message As String) ScriptManager.Regi...
ASP.NET: Creare una macchina di sviluppo per Share...
views 0
Seguendo questo il link c'è la spiegazione su come metter su una macchina per lo sviluppo di sharepoint http://weblogs.asp.net/erobillard/archi...
Utilizzare un web service con Jquery UI Autocomple...
views 1
Oggi, tra un caffè ed un'altro, ho messo on line una soluzione di esempio per utilizzare un web service (ASMX) come custom datasource per la fu...

Fin da bambino sono stato affascinato dall’informatica dove ho i primi approcci con il Commodore 64. Nel 98 ho iniziato ad affacciarmi nel mondo del lavoro ed ho sviluppato applicazioni client/server in VB per una piccola società di Roma. Affascinato da internet sono passato alla programmazione web, che seguo ancora oggi, passando per diverse tecnologie java, php, ASP, ASP.NET. Oggi sono contributors per il progetto ASP.NET Core MVC.