martes, 1 de mayo de 2012

Scripting en Silverlight

 

Hoy deseo escribir acerca del Scripting en Silverlight, pues esto me permitió solucionar un problema de negocio y considero apropiado hacerles partícipes, por si en algún momento lo llegan a requerir.

Bien, comencemos con el problema.

El problema o necesidad era poder ejecutar unos cálculos, con base en unas fórmulas, en una aplicación Silverlight, pero el usuario quería ser capaz de poder poder modificar dichas fórmulas a voluntad y que el aplicativo reconociera el cambio y las aplicase sin mayores traumatismos.

Comencé a buscar y lo que deseaba encontrar era una forma, para poder ejecutar el código expresado en una cadena de texto, quería encontrar un mecanismo parecido al Eval de JavaScript, pero que me funcionara en Silverlight.

Fruto de la búsqueda, surgieron varias posibilidades, todas inexploradas por mi hasta el momento y todas relacionadas con la aplicación de lenguajes dinámicos. Aquellos que usan o se construyen sobre el DLR ( Dynamic Language Runtime) de .NET  y cuyos ejemplos emblemáticos son: IronRuby o IronPython, implementaciones para .Net de los lenguajes dinámicos Ruby y Python.

En primer lugar, se exploró IronRuby y aunque, como pude comprobar con ejemplos, permitía la ejecución del código expresado en una cadena de texto. Mi problema requería otros aspectos adicionales: Ejecutar una fórmula (un texto), pero a la cual le pudiera definir el valor de los términos y de la cual pudiera obtener su resultado. Quizás, profundizando un poco más con IronRuby, hubiese podido resolver el problema. Sin embargo, como nos pasa muy a menudo, no tenía el suficiente tiempo, para hacer una exploración completa del lenguaje y, además, mi problema requería también que la sintaxis que usara fuera en C#, pues se trataba era de externalizar el trabajo con las fórmulas, es decir, ya se tenía el código y la lógica de la realización de los cálculos, donde la fórmula, por el momento se hacia sobre los términos, pero donde el usuario, si quería no la podía modificar. De haber concluido que la respuesta era IronRuby, habría tenido que traducir un código de C# a IronRuby, lo que hubiese requerido un esfuerzo adicional.

Enfocado ya en mi investigación sobre lenguajes dinámicos , descubrí Script.NET Language. Lo primero que noté, es que podía trabajar con la Sintaxis de C# y que al igual que con IronRuby podía ejecutar el código expresando en una cadena de texto. Incluso pude notar que era más fácil su utilización, comparada con IronRuby, en donde, todo se basa en referenciar en el proyecto de Silverlight un único assembly e interactuar con unos objetos y métodos casi intuitivos.

La página de donde lo puedes descargar si te interesa es esta:

http://www.protsyk.com/scriptdotnet/wiki/index.php?title=Main_Page

Bien, lo descargas y de la ruta de tu disco duro donde queda instalado (en mi caso):

C:\Program Files\Petro Protsyk\S#\Silverlight 4

Tomas la dll: Scripting.SSharp.Silverlight.dll

Y la llevas a una carpeta de librería que tengas, asociada al proyecto de Silverlight, donde quieres usar la funcionalidad de Scripting.

En mi caso, el proyecto es ScriptNet y luego de copiar la dll en una carpeta de librería asociada al proyecto la referencié en el proyecto Silverlight.

ScriptingNet1

En el App.xaml, en su Code-Behind, en el constructor y antes de InitializeComponent, colocar el código:

RuntimeHost.Initialize();

 


Esta  instrucción inicializa la característica de Scripting, para que pueda ser usada en cualquier página del proyecto. Si deseas solo usar la característica de Scripting en una página o User Control dado, debes colocar la instrucción antes del InitializeComponent de tu página o UserControl.


Para mi caso, tengo la siguiente página:


ScriptingNet2


Como se puede apreciar, en el primer caso, en el resultado del click del botón Calcular dato, se realiza el cálculo sin la fórmula externalizada; sin embargo, el resultado del click del segundo botón Calcular  fórmula, se realiza con base en la fórmula que se encuentra en la caja de texto correspondiente a la misma. Lo que resuelve de forma apropiada el problema que tenía.


Observar, como los resultados son exactamente iguales.


Ahora, démosle una mirada a la implementación del click de cada botón.


ScriptingNet3


Este es el caso normal, aquí se llama al método RealizarOperacion:


ScriptingNet4


Como vemos, se obtiene la información para los términos  y luego se calcula su valor en base a la fórmula, pero ésta no se encuentra externalizada.


A continuación, veremos el segundo caso:


ScriptingNet5


Observar, como la implementación del click es casi idéntica al del primer caso, solo que acá se obtiene la formula de la caja de texto y ésta se le pasa como parámetro a otra sobrecarga del método RealizarOperacion:


ScriptingNet6


Fijarse, como el código de la definición de los términos que participan en la fórmula permanece igual y lo que resta es:




  1. Definir el contexto, para la definición de las variables a participar en la fórmula.


  2. Definir los valores de las variables, que participarán en la fórmula, a través de context.SetItem.


  3. Ejecutar el texto, teniendo en cuenta los valores de las variables definidas en el contexto. (Script.RunCode).


  4. Obtener el valor que quedó como resultado en alguno de los ítems definidos en el contexto. (context.GetItem).

Esto permite, la modificación de la fórmula, en cualquier momento y sin la afectación del código, lo que resuelve, perfectamente, el problema.


Veamos como, a continuación, se modifica la fórmula, sumando 10 y el resultado es el apropiado y el código de la realización de la operación no cambia:


ScriptingNet7


Listo, espero que les haya gustado y que les sirva tanto como a mí. Este Script.NET, amplia el rango de acción de Silverlight y colabora, para que la afirmación de que en Silverlight el límite es tu imaginación sea siempre vigente.