Image is unrelated to the post; just an awesome view from my building
« This post is part of the combined
IronRuby and AgDLR release at MIX '09
While many developers love to program in dynamic languages like Python or Ruby, they may not have that freedom in their day-to-day jobs, for a variety of tecnical and business reasons. However, dynamic languages are as useful when embedded in existing software, possibly making the design better than a non-scripting-enabled version. Languages based on the dynamic language runtime are really easy to embed in .NET applications, so hopefully this post inspires you to add scripting support to your applications.
In a previous post, I showed how to build a C# Silverlight application which evaluated a line of dynamic language code and printed the result. This post also touched on the philosophical issues around dynamic and static languages, so definitely give it a read first. Combining this with my most recent post about testing a C# Silverlight Calculator with IronRuby, this post will walk you through adding the ability to define calculator functions in IronPython.
Note: the same practices apply when scripting your application with IronRuby, but it’s been a while since I gave IronPython some love.
Also, Kirill Osenkov, a C# IDE QA'er, wrote up a similar article about Graphing IronPython functions in Silverlight, so check that out as well.
First off, download the Silverlight Calculator solution that we will build upon.
Download Calculator (start)
To cheat or follow along while reading,
download the finished Calculator from the MIX '09 Demos repository.
Sanity check: You'll need ASP.NET MVC 1.0 and Silverlight 3 Tools installed (SL2 might work, might not). Make sure Calculator.Web
is the start project, and make sure CalculatorWebTestPage.aspx is the start page (both can be set by right-clicking on the respective files). Also make sure the site opens to CalculatorTestAppTestPage.aspx?test
so that the tests run automatically. Compiling and running this solution should show you the following:
This project gives us some UI to type Python code into (Page.xaml will show you exactly what XAML creates this), and adds references to the IronPython and DLR binaries.
Now for the interesting part; building a PythonEngine
class to encapsulate all the Python execution. Open Calculator.Tests\Calculator.Tests\tests\python_engine_test.rb
(yes, Ruby is sneaking back into this post) and let's write some tests...
Now open CalculatorTestApp\Page.xaml.cs
and add this to the CalculatorTestApp namespace to make those tests pass...
Pretty simple. The code sets up a ScriptEngine
for IronPython, executes arbitrary Python code in a shared scope, finds all the defined methods in that shared scope, and can call those methods with a single parameter. All in ~23 lines of code. Awesome. Here it is in action...
Now the Calculator is ready to be scripted. The end goal is to:
-
Execute the code as it's being typed into the Calculator
-
If it does not produce an error ... find out all the valid top-level methods defined by the code and add buttons to the UI for each method.
-
Clicking the button will call the appropriate method, sending the calculator's current result as a argument, and the return value will be the new result of the calculator.
So let's write tests for this ...
And the following will make it all pass...
And now giving it a run will produce the following:
Clicking the button's above the Python code will call that function, sending the Calculator's current value as the first argument. Pretty cool! And that's all there is to it. Adding scripting support to applications on the desktop is just as simple. So, don't be afraid of this new-found power, go build awesome stuff with it!