Un ExpressionBuilder per recuperare stringhe nazionalizzate da database

di Cristian Civera, in ASP.NET 2.0, Expression Builders,

Tra le novità di ASP.NET vi è l'introduzione di una nuova sintassi utilizzabile nel codice delle nostre pagine ASP.NET. Delimitando con

<%$ %>

una stringa, il parser di ASP.NET crea in funzione del prefisso utilizzato una espressione. Di default sono presenti tre prefissi:
- AppSettings: recupera dalla collezione appSettings del web.config;
- ConnectionStrings: recupera una stringa di connessione dalla collezione connectionStrings del web.config;
- Resources: recupera qualsiasi oggetto presente nelle risorse del sito web-

Se indichiamo per esempio nella configurazione una chiave:

<configuration>
  <appSettings>
    <add key="key1" value="Test key1" />
  </appSettings>
</configuration>

e in una pagina ASP.NET inseriamo il seguente codice:

<asp:Label ID="test" runat="server" Text="<%$ AppSettings: key1 %>" />

la pagina risultante avrà una label con testo "Test key1". Il concetto è molto semplice, ma molto comodo.

Il segreto sta negli expression builders associati ad ogni prefisso. Poiché la pagina alla prima esecuzione viene parserizzata e convertita in codice .NET che crea i controlli (in questo caso la Label), è necessario che venga generato del codice .NET che restituisca il valore da assegnare alla proprietà Text in funzione dell'espressione "key1".

Al fine di capire meglio il funzionamento creiamo un expression builder che recuperi una stringa da database in funzione di una chiave, situazione frequente in motori di CMS multilingue.
Creiamo quindi una classe di nome DBResourceExpressionBuilder ed ereditiamo da System.Web.Compilation.ExpressionBuilder, sovrascrivendo il metodo GetCodeExpression.
Tale membro riceve il controllo e altre informazioni sul controllo che si sta caricando, tra cui l'espressione. Il parser chiamerà questo metodo quando si troverà di fronte ad un

<%$ DBResources: xxx %>

In questa funzione non dobbiamo fare altro che restituire un CodeExpression e cioè la rappresentazione delle righe di codice in C#, VB 2005 o qualsiasi altro linguaggio che supporti il framework, tramite modello ad oggetti. Tutti questi linguaggi hanno infatti una stessa logica in comune, perciò tramite CodeDOM è possibile rappresentarli in forma unica.
Ecco il codice di quanto appena detto:

[ExpressionPrefix("DBResources")]
public class DBResourceExpressionBuilder : ExpressionBuilder
{

    public override System.CodeDom.CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
    {
        string key = entry.Expression;

        // Recupero il riferimento al type
        CodeTypeReferenceExpression target = new CodeTypeReferenceExpression(typeof(DBResourcesManager));

        // Riferimento alla chiave
        CodeExpression keyExpression = new CodePrimitiveExpression(key.Trim());

        // Riferimento al metodo di DBResourcesManager
        CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression(target, "GetResource");

        // Invocazione del metodo
        CodeMethodInvokeExpression method = new CodeMethodInvokeExpression(methodReference, keyExpression);

        return method;
    }

In pratica abbiamo scritto tramite classi quello che scritto in C# sarebbe:

DBResourcesManager.GetResource("chiave")

DBResourcesManager è una nostra classe con membro statico e fa il lavoro di prelevare dal database la stringa e non è importante al fine di questo script.
Fatto questo non ci resta che indicare al motore il nostro expression builder, inserendolo nel web.config:

<configuration>
  <system.web>
    <compilation debug="true" >
      <expressionBuilders>
        <add expressionPrefix="DBResources" type="DBResourceExpressionBuilder"/>
      </expressionBuilders>
    </compilation>
  </system.web>
</configuration>

Ora possiamo usarlo nella nostra pagina nel seguente modo:

<asp:Label ID="welcome" runat="server" Text="<%$ DBResources: WELCOME_MESSAGE%>" />

Se guardiamo il codice autogenerato in C# troveremo la seguente riga di codice sull'iniziazione della label:

@__ctrl.Text = System.Convert.ToString(DBResourcesManager.GetResource("WELCOME_MESSAGE"), System.Globalization.CultureInfo.CurrentCulture);

Si tratta di un'assegnazione ad una proprietà di un controllo, perciò bisogna prestare attenzione al fatto che gli expression builders possono essere utilizzati solo in tag aventi l'attributo runat="server" e solo su proprietà che il controllo dispone.

Ora il nostro expression builder è completo. Nell'esempio trovate anche il designer associato per avere supporto in Visual Studio 2005.

Questa nuova sintassi insieme ai build providers ci permette di intervenire alla fase di compilazione delle pagine e apre la strada a scenari molto utili sia in termini di performance, poiché è tutto precompilato, sia in termini di comodità di utilizzo.

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