Image is unrelated to the post; just an awesome view from my building
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.
First off, download the Silverlight Calculator solution that we will build upon.
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:
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...
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!