Forum di AAC   |      Messaggi privati   |      English



ArcadiA Club
ArcadiA Club






Home Page   Home Page
programmazione.htm   Programmazione - FORUM sezione  Vai al FORUM
 
Username:
Password:
Iscriviti!  |  Recupero password



Iscriviti GRATIS, potrai navigare senza questa
fascia e accedere a contenuti esclusivi:

    E-Mail:

Password:



 
 

 
- Eval in .Net: compilare codice a run-time -
 
COSA SERVE PER QUESTO TUTORIAL
 Download | Chiedi sul FORUM | Glossario conoscenze basiche di VB .Net
Eseguire a run-time codice VB, C#, J# e JScript.Net in una stringa

EVAL IN .NET: COMPILARE A RUN-TIME
Colmare l'ultima differenza con i linguaggi di scripting tramite CodeDomProvider

La maggior parte dei linguaggi di scripting come PHP, Python e Javascript per via della loro versatilità permettono di eseguire stringhe di codice a run-time tramite la funzione comunemente chiamata eval. Ad esempio in Javascript:

eval("alert('Codice in una stringa!')");

Il fatto di essere interpretati permette di eseguire codice "al volo". I linguaggi .Net invece richiedono una compilazione e per questo il framework non mette a disposizione funzionalità come eval. Tuttavia la compilazione può anche essere eseguita a run-time e senza l'uso di tool da linea di comando (come cs.exe, vb.exe e così via). Esistono infatti per ogni linguaggio (o per lo meno per quelli forniti da Microsoft) una classe che eredita da CodeDomProvider (in System.CodeDom.Compiler) che mette a disposizione una serie di metodi per effettuare una compilazione a run-time senza complicazioni. Le classi per VB .Net e C# sono incluse in System.dll mentre per gli altri due linguaggi che qui tratteremo, JScript.Net e J#, è necessario aggiungere un riferimento rispettivamente a Microsoft.JScript.dll e VJSharpCodeProvider.dll. A questo punto sorge spontanea la domanda: perché non si parla di Managed C++ (chiamato anche C++.Net) e C++/CLI? Semplicemente perché pur esistendo la classe CodeDomProvider per questi linguaggi (in CppCodeProvider.dll) sia per Managed C++ (CppCodeProvider7) e C++/CLI (CppCodeProvider) i metodi per compilare da una stringa di testo non sono stati implementati.
Ricapitoliamo le classi che ci interessano:

  • Microsoft.CSharp.CSharpCodeProvider in System.dll per C#;
  • Microsoft.VisualBasic.VBCodeProvider in System.dll per Visual Basic .Net;
  • Microsoft.JScript.JScriptCodeProvider in Microsoft.JScript.dll per JScript .Net;
  • Microsoft.VJSharp.VJSharpCodeProvider in VJSharpCodeProvider.dll per J#;

Ricordiamo che J# non è normalmente incluso nel Framework .Net e per questo potrebbe essere necessario scaricarne le librerie.
Compilare codice è in sé molto semplice, sono sufficienti solo alcune di righe di codice:


Dim strAssemblyName As String = "EvalCode"
Dim cd As System.CodeDom.Compiler.CodeDomProvider
cd = New Microsoft.VisualBasic.VBCodeProvider()
Dim cmpParameters As New System.CodeDom.Compiler.CompilerParameters( _
    New String() {"System.dll"}, strAssemblyName & ".dll")
Dim cmrResults As System.CodeDom.Compiler.CompilerResults
cmrResults = cd.CompileAssemblyFromSource(cmpParameters, strCode)

Per prima cosa bisogna istanziare il CodeProvider corretto (tra quelli citati sopra), creare un oggetto CompilerParameters specificando una lista di librerie a cui fare riferimento e il percorso dove creare l'assembly (in questo caso EvalCode.dll), e infine richiamare il metodo CompileAssemblyFromSource passandogli l'oggetto CompilerParameters e il codice da compilare. Verrà restituito un oggetto CompilerResults con i risultati e gli errori della compilazione.
Si ricordi che eseguire codice inserito dall'utente è un'operazione molto rischiosa in quanto ha la possibilità di accedere in maniera completa al vostro sistema. Per proteggersi da questa evenienza è possibile limitare i permessi di esecuzione utilizzando un AppDomain con accessi ristretti, ma questa procedura trascende l'obiettivo dell'articolo.
Ovviamente il codice che gli si passa deve essere compilabile, ovvero non è possibile semplicemente compilare "Console.WriteLine(Now.ToString())", deve essere all'interno di un metodo a sua volta all'interno di una classe. Ecco una serie di contesti validi per i linguaggi presi in considerazione.
Per Visual Basic .Net:


Imports System
Namespace EvalCode
    Public Class Execute
        Private strOutput As String = [String].Empty
        Public Function Main() As String
            {0}
            Return strOutput
        End Function
        
        Public Sub o(str As String)
            strOutput &= str
        End Sub
    End Class
End Namespace

Per C#:


using System;
namespace EvalCode {
    public class Execute
    {
        private string strOutput = String.Empty;
        public string Main()
        {
            {0}
            return strOutput;
        }
        public void o(string str)
        {
            strOutput = strOutput + str;
        }
    }
}

Per JScript .Net:


import System;
package EvalCode {
    public class Execute
    {
        private var strOutput : String = String.Empty;
        public function Main() : String
        {
            {0}
            return strOutput;
        }
        public function o(str : String)
        {
            strOutput = strOutput + str;
        }
    }
}

Per J#:


package EvalCode;
import System.*;

public class Execute
{
    private String strOutput = String.Empty;
    public String Main()
    {
        {0}
        return strOutput;
    }
    public void o(String str)
    {
        strOutput = strOutput + str;
    }
}

Nota: "{0}" indica dove va inserito il codice; si noti inoltre che per ogni linguaggio è stato scritto, oltre a Main, un metodo o() che aggiunge una stringa all'output: esso può rivelarsi comodo da utilizzare.

A questo punto non resta che usare un po' di Reflection per caricare l'assembly in memoria e richiamare un metodo creato (nel nostro caso Main).


'Creiamo l'oggetto AssemblyName che ci servirà per identificare il nostro assembly
Dim asnName As New System.Reflection.AssemblyName(strAssemblyName)
asnName.CodeBase = strAssemblyName & ".dll"
asnName.Name = strAssemblyName

'Creiamo un'istanza dell'assembly
Dim asbInstance As Reflection.Assembly = Reflection.Assembly.Load(asnName)
'Namespace e nome della classe in cui si trova il codice da eseguire
Dim strClassName As String = "EvalCode.Execute"
'Creiamo un'istanza della classe sull'assemblt precedentemente richiamato
Dim objClassInstance As Object = asbInstance.CreateInstance(strClassName)
'Prendiamo il tipo della classe in questione
Dim typClass As Type = asbInstance.GetType(strClassName)

Dim strOutput As String
'Tramite il tipo richiamiamo il metodo Main (si tratta di una funzione dunque usiamo la binding-flag
'InvokeMethod) sull'istanza precedentemente creata (objClassInstance). Non passiamo parametri.
strOutput = CStr(typClass.InvokeMember("Main", _
    Reflection.BindingFlags.InvokeMethod, Nothing, objClassInstance, Nothing))
<< INDIETRO by VeNoM00  


Video collegati Visualizza i video di questa pagina
Visualizza video sull'argomento "eval".
Visualizza video sull'argomento "compilare".
Visualizza video sull'argomento "runtime".
Visualizza video sull'argomento "eval net compilare runtime".


Dì la tua: cosa ne pensi?
Esponi il tuo punto di vista e condividilo con migliaia di persone

Oggetto nuova discussione:


Testo del messaggio:

E-Mail:

Quanto fa più dieci:




Una discussione di questa sezione

TeamViewer: un'applicazione utile, efficace e gratuita

Quante volte ci è capitato di avere un problema improvviso al pc e di non avere idea di dove mettere le mani per risolverlo? Oppure non è raro, soprattutto in ufficio, di dover svolgere in fretta determinati lavori e trovarsi in difficoltà di fronte ai passaggi più complicati senza avere l'opportunità di ricevere aiuto? Tutto ciò potrebbe diventare soltanto un lontano ricordo grazie ad una...

LEGGI TUTTA LA DISCUSSIONE


Risposta 1

Grazie del link, la prossima volta che la mia ragazza non saprà come fare una cosa al pc, invece di impazzire al telefono con spiegazioni insensate le farò vedere tutto direttamente sul suo pc!:D

LEGGI TUTTE LE RISPOSTE


Risposta 2

Forte! Mi associo a spikeloris4, ho già testato il tutto!

LEGGI TUTTE LE RISPOSTE

 





^ TOP  
Linkaci | Segnala errore | Invita | Stampa


pubblicità | regole | visione | diritti | ufficio stampa | donazioni | scrivici
© 1999-2012 - P.IVA 02284690035 - Grafica, layout e contenuti sono di esclusiva proprietà di ArcadiA Club.

Powered by:
Spazi pubblicitari di alto livello
 

Compra in un click! | Cerca prodotti in offerta: