Dynamic Languages Support in Silverlight
As I've mentioned in my last post, I'm posting a chapter of the Silverlight article that we've published. The following is the introduction to the dynamic languages in Silverlight.
Dynamic Languages Support in Silverlight
One of the most innovative features of Silverlight new version is the Dynamic Languages Support. To start, let's make a brief introduction to this kind of languages, so that we can show some code.
Introduction to Dynamic Languages
The Dynamic Languages are those that in execution time perform lots of tasks that other languages perform in compilation time. For instance: The typing is, generally, dynamic. This means that in coding and compiling time there may not be an explicit type definition; this operation is performed in execution time. This interesting feature opens lots of possibilities (we can create and modify types and code during the execution of our program).
We can see the expressive power of this kind of languages. If you are not familiarize with this you may find it a little confusing, but eventually you will be able to program in a very clear and elegant way.
Some of these languages are Python, Ruby, Smalltalk and JavaScript. They are widely used due to its portability and speed of develop and execute. Just to name a few examples, Google and BitTorrent have lots of its coding in Python.
Implementation in Silverlight
Silverlight includes a Dynamic Language Runtime (DLR) which is executed above the Common Language Runtime (CLR). Its responsibility is to provide the compiler the functionality to support dynamic languages. Note that the CLR was not modified in this version of the .Net Framework. The DLR is in charge of generating the code, make the dynamic typing and manage the execution environment of the dynamic code blocks. Currently there's support for IronPython (Python's implementation) and IronRuby (Ruby's implementation). There will also support JavaScript (EcmaScript 3.0) and VisualBasic (VBx).
One of the objectives is to provide interoperability between these languages and also to use others (we could make an implementation of SmallTalk and then integrate it with our applications through the DLR). In addition, it offers the communication with the Framework components.
Examples
Now that the introduction is over, let's see some code! First of all, we are going to show some examples using IronPython, because is one of the most robust dynamic languages. Besides, the latest version of Visual Studio 2008 offers debugging. It's recommended to have a basic knowledge of IronPython to make the most of the language; anyway we'll see some simple examples.
A Silverlight application that uses Python has the same components of any other: the CreateSilverlight.js, Silverlight.js y page.xaml files. The difference is that now we'll have a page.xaml.py file, which will contain our Python code.
First of all let's create the files mentioned above. An error will be raised if we have a code-behind class (ie. page.xaml.cs) and a Python handler (page.xaml.py). If this happens, we'll see a parsing error very unpleasant (AG_E_PARSER_INVALID_XCODE_TAG). It's fixed by deleting the code-behind file and the x:Class tag of the first element in the Xaml file.
Then we have to state that the page has an event handler that must be executed by the IronPython host. To do this, the first element that we need to add is the x:Code:
<x:Code Source="page.xaml.py" Type="text/ironpython" />
Doing this we specify the file path and the host that will be used.
Let's open the .py file. First of all, we'll add the references to the .Net Framework components:
import clr
import System
Now we add a TextBlock with a handler for the MouseLeftButtonDown event:
<TextBlock
x:Name="text"
Loaded="OnLoad"
MouseLeftButtonDown="OnClick"
Width="400"
TextWrapping="Wrap" Text="Example" />
At this point we should define the OnClick method, so will write a function in the Python file. Well, let's look at an easy implementation:
def OnLoad(sender, e):
sender.Text = "Ejemplo"
def OnClick(sender, e):
sender.Text = "Clickeado"
Where sender is the control that raises the event and e contains the arguments. The only thing that will happen is that the control's text will change, maintaining the user experience offered by Silverlight (executing the event without a postback).
Other concept to take into account is the utilization of variables. Every IronPython execution environment has a globals() property. It returns a dictionary in which we can store the variables that we want them to have a global scope. For instance:
globals() #returns the dictionary
globals()["a"] #returns the "a" variable
globals()["a"] = 1 #assigns a 1 to "a"
Now we can use the global variables in the event handlers:
def OnLoad(sender, e):
globals()["cont"] = 0
sender.Text = "Example"
def OnClick(sender, e):
a = globals()["cont"]
sender.Text = a.ToString()
a = a + 1
globals()["cont"] = a
And at every click on the TextBox we'll see that its value increments.
Despite the fact that the examples shown are very simple, we see that we can use the most of the Python features combined with the .Net components: Reflection, Web Services, our classes, and so on.
Moving on, let's take a look at another IronPython feature: the power to create an execution engine to manage the code execution in runtime. To do this, we must add a reference to the IronPython component:
import IronPython
from IronPython.Hosting import PythonEngine
In this namespace will find the classes used to implement the Python host functionality. What's interesting is that our applications can use it. First of all we'll invoke it:
py = PythonEngine.CurrentEngine
In py we have the engine instance. Then we can use the Execute method to execute in runtime any code that we want.
py.Execute(code, module)
To sum up, this is the entire function:
def engineTest():
py = PythonEngine.CurrentEngine
py.Execute("text.Text = 'Changed by the engine' ",
py.CreateModule("temp"))
And now we can create our execution engine, using the one that the Framework provides.