- 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.
Ricordiamo che J# non è normalmente incluso nel Framework .Net e per
questo potrebbe essere necessario scaricarne le librerie. 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. 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 |