Inizializzazione modulare di un'applicazione ASP.NET 4.0

di Marco De Sanctis, in ASP.NET 4.0,

Solitamente, quando dobbiamo eseguire codice di inizializzazione per un'applicazione ASP.NET, siamo abituati a sfruttare il metodo Application_Start contenuto all'interno di global.asax, che però risulta poco pratico nel momento in cui ci sia la necessità di gestire dipendenze da altri assembly, ognuno con la propria procedura di startup.

Immaginiamo, ad esempio, il caso in cui stiamo sfruttando Unity come container di Inversion of Control, esponendo i servizi applicativi tramite interfacce la cui implementazione concreta si trova in uno o più assembly che la nostra applicazione referenzia. Tipicamente, per configurare il nostro sistema abbiamo a disposizione due strade:

  • Utilizzare un approccio centralizzato e basato su XML, ad esempio sfruttando il file di configurazione web.config, ma perdendo però ogni tipo di supporto da parte del designer di Visual Studio;
  • Fare in modo che ogni assembly sia in grado di registrare autonomamente i propri oggetti sul container.

Il vantaggio della prima soluzione è quello di poter intervenire sulla configurazione a caldo, senza cioè essere costretti a ricompilare l'applicazione web. Il secondo approccio, invece, è sicuramente più strutturato, e può essere implementato piuttosto facilmente, ad esempio realizzando all'interno di ogni assembly un metodo statico simile al seguente.

public class Initializer
{
  public static void Initialize()
  {
    ServiceLocator.Container
      .RegisterType<ICustomerRepository, CustomerRepository>();
    // ... registrazione di altri servizi
  }
}

Lo svantaggio risiede però nel fatto che siamo comunque costretti a invocare questi metodi all'interno di Application_Start, come nell'esempio seguente, con la necessità di effettuare una ricompilazione dell'applicazione nel caso le dipendenze varino. Inoltre, l'inizializzazione deve essere eseguita prima di ogni altro codice di Application_Start, perché quest'ultimo potrebbe potenzialmente utilizzare il container e quindi richiedere che sia completamente configurato.

protected void Application_Start()
{
  Module1.Initialize();
  Module2.Initialize();
  // altri moduli da inizializzare
  // ...
  // qui codice che sfrutta i moduli inizializzati
}

Nel caso di un'applicazione ASP.NET 4.0, tuttavia, esiste una terza soluzione, che presenta i vantaggi di entrambe le alternative che abbiamo presentato, e che si basa sull'utilizzo dell'attributo PreApplicationStartMethod. Tramite esso, possiamo specificare un metodo, all'interno di un assembly, che verrà automaticamente eseguito dal runtime di ASP.NET prima della fase di startup, e quindi prima anche del metodo Application_Start.

[assembly: PreApplicationStartMethod(typeof(Initializer), "Initialize")]

public class Initializer
{
  public static void Initialize()
  {
     ServiceLocator.Container
       .RegisterType<ICustomerRepository, CustomerRepository>();
  }
}

Il metodo in questione deve essere statico e privo di parametri. L'aspetto interessante è che questo attributo viene automaticamente individuato tra tutti gli assembly presenti nella cartella \bin, anche se non referenziati dal progetto ASP.NET. Il risultato, quindi, è che se ogni class library possiede il proprio metodo di inizializzazione, di fatto possiamo riconfigurare le dipendenze semplicemente copiando i relativi assembly all'interno della cartella dell'applicazione.

Non è questo l'unico scopo dell'attributo PreApplicationStartMethod: la sua natura, ad esempio, lo rende un'ottima soluzione per configurare a runtime HttpModule, BuildProvider o aggiungere riferimenti a runtime.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi