|
- 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 | ||