Me explico:
1. Tengo las variables:
cComando1 = "FOR i = 1 TO 100: ?'prueba': NEXT" (ejecutar un bucle)
cComando2 = "IF X=Y THEN Z=5" (ejecutar una comparacion)
cComando3 = "miFuncion(parametros)" (ejecutar una funcion)
2. Ahora, deseo ejecutar dichos comandos, interpretando
el contenido de estas variables.
En Clipper, a esto se llama, macro-sustitucion, porque
sustituye el valor de una variable, por su verdadero
contenido. En clipper, se hacía así:
Resultado = &cComando (el operador &).
también se usaban un tipo de dato llamado CodeBlocks.
En el VB6 ya tengo una función que hace esto, pero
al importarlo al VS.NET ya no funciona.
Alguien sabe como hacerlo ?
Gracias.
Recuerdo bien los "codeblocks" de Clipper. Y el operando de
macrosustitución. Era una curiosa funcionalidad que se perdió cuando pasamos
a lenguajes Windows. En VB6 existía una cosa llamada CallByName() que
permitía hacer algo -en ocasiones- parecido, pero no era esa funcionalidad
exacta. Posteriormente, cuando esta cuestión ha vuelto salir, los
comentarios iban por intérpretes de Script, y en concreto por el componente
COM MSScriptControl (que a pesar del nombre no es un control, sino
componente). Dispone de métodos ExecuteStatement() y Run() que ejecutan el
código que se le ha añadido con ciertas restricciones.
Si haces referencia a los componentes en .NET podrás usarlo a través de
Interop, porque todavía esta en la lista de componentes COM...
--
Saludos cordiales,
Marino Posadas
MCSD, MCT, MSF-P
www.ElAveFenix.net
"Carlos Bardales" <bard...@yahoo.com> wrote in message
news:7948860d.0301...@posting.google.com...
Por interpretación, tal y como Clipper o VB lo hacen, utilizando como
lenguaje VBScript (lo que harías en VB).
Solo tienes que añadir a tu cuadro de taréas el componente "Script Control
Object" y desde allí añadirlo a tu formulario. Ahora podrás ejecutar este
código:
Dim comando = "FOR I = 1 TO 100: MsgBox i: NEXT"
AxScriptControl1.ExecuteStatement(comando)
Por compilación. A través de la clase VBCodeProvider, con la cual puedes
compilar código en memoria y ejecutarlo sobre la marcha mediante reflection.
Me parece con mucha diferencia la mejor opción, pese a ser ligeramente más
complicada. Permite ejecutar CUALQUIER VB.NET, no VBScript, y además el
código es compilado, con lo cual la depuración es muchísimo más sencilla y
la ejecución más rápida. Puedes crear cualquier programa, depurarlo con
vs.net y una vez probado, asignarlo al string fuente. Eso si, hay que tener
cuidado con el tema de espacios de nombre y de referencias (solo añado
WinForms en el ejemplo)
Dim fuente As String = _
"Imports System.Windows.Forms" & vbCrLf & _
"Public Class ClaseEjecuta" & vbCrLf & _
"Public Shared Sub Ejecuta()" & vbCrLf & _
"Dim i as Integer" & vbCrLf & vbCrLf & _
"For i = 1 To 10" & vbCrLf & vbCrLf & _
"MessageBox.Show(i.ToString())" & vbCrLf & _
"Next i" & vbCrLf & _
"End Sub" & vbCrLf & _
"End Class"
Dim codeProvider As New VBCodeProvider()
Dim compilador As ICodeCompiler = codeProvider.CreateCompiler()
Dim parametros As New CompilerParameters()
'Puedes añadir otras referencias necesarias
parametros.ReferencedAssemblies.Add("System.Windows.Forms.dll")
parametros.GenerateInMemory = True
Dim resultado As CompilerResults =
compilador.CompileAssemblyFromSource(parametros, fuente)
If resultado.Errors.Count > 0 Then
Dim errores As String = ""
Dim mensaje As CompilerError
For Each mensaje In resultado.Errors
errores += "Error " & mensaje.ErrorNumber & ": " &
mensaje.ErrorText & vbCrLf
Next
Throw New Exception(errores)
End If
'ClaseEjecuta se corresponde con el nombre de la clase declarado en
fuente.
Dim clase As Type = resultado.CompiledAssembly().GetType("ClaseEjecuta")
'Ejecuta se corresponde con el nombre del método declarado en fuente.
clase.GetMethod("Ejecuta").Invoke(Nothing, Nothing)
--
Juan Carlos Badiola
MVP - C#
Carlos Bardales
"Marino Posadas" <mpos...@eidos.es> wrote in message news:<#6wkB1NwCHA.2372@TK2MSFTNGP09>...
--
Saludos cordiales,
Marino Posadas
MCSD, MCT, MSF-P
www.ElAveFenix.net
"Carlos Bardales" <bard...@yahoo.com> wrote in message
news:7948860d.03012...@posting.google.com...
Quedo muy agradecido con Juan Carlos Badiola y con otros miembros
de este foro que me han ayudado, a pesar de ser nuevo en el mismo,
personas como ustedes hacen posible que aprendices como yo,
seamos un poco menos ignorantes.
Muchas gracias.
Ahora, estoy haciendo algunas pruebas para crear una funcion
genérica que utilice este interprete de comandos.
La idea es que a esa función, se le pase el comando que se desea
interpretar, y que la función devuelva el resultado de la ejecución
de dicho comando, como lo hacen las funciones normales.
Ejemplo:
Dim resultado as string
Resultado = EjecutarCmd( "IIF(5=4,'Falso','Verdadero')" )
Pienso que debe de existir alguna forma de devolver dicho valor.
Otra cosa, el interprete al indicarle algo que va entre comillas
simples, lógicamente interpreta que lo que sigue es un co-
mentario, por lo que da un error en tiempo de ejecución.
Perdón Juan Carlos, abusando de tu tiempo, tienes alguna idea
que cómo podría hacerse ?
De nuevo, Gracias mil.
Carlos Bardales,
"Tristan" <jcba...@hotmail.com> wrote in message news:<#AIaUBOwCHA.2292@TK2MSFTNGP10>...
Juan Carlos Badiola
Tiene un método shared Eval, de forma que puedes evaluar
en tiempo de ejecución cualquier expresión de forma
simple. Además mediante los miembros de instancia, permite
añadir código, compilarlo, y llamar a los métodos añadidos.
Este es un ejemplo de uso:
MsgBox(Evaluator.Eval("3 + 3").ToString())
Dim evaluador As New Evaluator()
Dim codigo As String = "return a + b"
evaluador.AddFunction("Suma", "a as integer, b as
integer", codigo)
evaluador.Compile()
'Ahora no face falta recompilar para las sucesivas llamadas
'ya que la función tiene parámetros
MsgBox(evaluador.EvalFunction("Suma", 2, 3).ToString())
MsgBox(evaluador.EvalFunction("Suma", 12, 23).ToString())
'Y ahora un procedimiento
codigo = _
"Dim i as Integer" & vbCrLf & _
"For i = 1 to limite" & vbCrLf & _
"MessageBox.Show(i)" & vbCrLf & _
"Next"
evaluador.AddSub("Bucle", "limite as integer", codigo)
evaluador.ImportsList.Add("System.Windows.Forms")
evaluador.References.Add("System.Windows.Forms.dll")
evaluador.Compile()
evaluador.CallSub("Bucle", 7)
En VB, para incluir comillas dentro de un string, basta
con poner comillas dobles, el apóstrofe no se puede usar
en su lugar. Es decir:
En lugar de:
Resultado = EjecutarCmd( "IIF(5=4,'Falso','Verdadero')" )
Tendrías que poner:
Resultado =
EjecutarCmd( "IIF(5=4,""Falso"",""Verdadero"")" )
O utilizando mi clase:
Resultado = Evaluator.Eval("IIF
(5=4,""Falso"",""Verdadero"")").ToString()
Saludos
Carlos Bardales