Compilazione dinamica del codice in una pagina ASP.NET

di Andrea Zani, in UserScript, ASP.NET, VB.NET,

Ci sono casi estremi in cui è necessario poter utilizzare il caro vecchio comando "eval" presente in Javascript per eseguire del codice "costruito" durante l'elaborazione della nostra pagina o perché preso da fonti come directory remote, database, ecc... Con i linguaggi del .NET Framework non c'è un modo nativo, ma possiamo ricrearla con pochi passaggi.

Immaginiamo di voler includere una classe con una funzione all'interno della nostra pagina, di questo tipo:

imports System
imports System.Web

public class Miaclasse
  public sub Scrivi(frase as string)
    HttpContext.Current.Response.Write(frase)
  end sub
end class

Per poterla compilare dinamicamente dall'interno del nostro codice dovremo scrivere:

<%@ Page language="VB" %>
<%@ Import namespace="System.Reflection" %>
<%@ Import namespace="System.CodeDom.Compiler" %>
<%@ Import namespace="Microsoft.VisualBasic" %>
<script runat="server">

sub Page_Load()

  Response.Write("Inizio compilazione ed esecuzione codice...<br />")

  ' dichiarazione classi per la compilazione di una classe per il web
  dim comp as ICodeCompiler = new VBCodeProvider().CreateCompiler()
  dim cp as new CompilerParameters()
  cp.ReferencedAssemblies.Add("system.dll")
  cp.ReferencedAssemblies.Add("system.Web.dll")
  cp.GenerateExecutable = false
  cp.GenerateInMemory = true

  ' codice che sarà compilato
  dim codice as string = "imports System" + vbCrLf + _
                         "imports System.Web" + vbCrLf + _
                         "public class Miaclasse" + vbCrLf + _
                         "  public sub Scrivi(frase as string)" + vbCrLf + _
                         "    HttpContext.Current.Response.Write(frase)" + _
                         vbCrLf + "end sub" + vbCrLf + "end class"

  dim cr as CompilerResults = comp.CompileAssemblyFromSource(cp, codice)

  ' in caso di errore di compilazione viene visualizzato l'elenco degli errori
  if cr.Errors.HasErrors then
    dim errore as string=String.Empty
    errore+="Error Compiling Expression:<br /> "

    for each err as CompilerError in cr.Errors
      errore+=err.ErrorText+"<br />"
    next
    Response.Write("Errore nella compilazione: " + errore)
  else
    ' Altrimenti viene eseguito il codice con la funzione presente.

    dim a as System.Reflection.Assembly
    a = cr.CompiledAssembly
    dim compilato as object = a.CreateInstance("Miaclasse")
    dim mi as MethodInfo = compilato.GetType().GetMethod("Scrivi")
    mi.Invoke(compilato, new object() {DateTime.Now.ToString()})
  end if

  Response.Write("<br />Fine elaborazione codice")
end sub

</script>

Ovviamente la cosa ha più senso se il codice viene letto da file system o da un database.
Il listato è abbastanza commentato e semplice. In questo esempio viene utilizzato il compilatore VB.NET, ma nulla ci vieta di utilizzare l'equivalente C#, modificando la linea:

comp=new VBCodeProvider().CreateCompiler()

in:

comp = new CSharpCodeProvider().CreateCompiler()

In questo modo possiamo includere codice di diversi linguaggi in un'unica pagina.

Si può trovare un buon articolo su questo argomento per approfondimenti su:
http://www.codeproject.com/csharp/runtime_eval.asp

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