Adding scripting to a C# Silverlight app

18 Nov 2008

The Minority

At Microsoft, the people I work with and I are definitely the minority, preaching about the benefits of dynamic languages and using the right tools for the right jobs, as in don't use static languages where you don't need it -- though there are plenty of times where you need it.

And now you ask, "Jimmy, but why would I, someone who gets paid to write C#, use a dynamic language?"

The majority would only have static languages pulled from their cold, dead fingers, and I totally agree with them. Don't change for the sake of change. Though, for certain scenarios, running scripts in a VB/C# application would be useful. For example, a shopping application that has a bunch of business rules, like "when someone has three items in their cart that all have to do with cooking, give them 10% off." These type of rules can change all the time, and traditionally you'd either store the rules in a database and implement a engine to understand the rules, or hand-code them yourself and have to redeploy the system every time you want to change them.

Or, you could save yourself the hassle and store the rules as Python or Ruby code, and then host the DLR in your application to run the code. Want to update the rules? Just update the code, nothing more. And a dynamic language is probably closer to how the domain-expert would represent them as, so they could even write them. Yes, this is just one scenario, but a powerful one for existing static language developers. This was the last part of my Seattle CodeCamp talk -- how to host the DLR in your C# Silverlight application.

Starting with an existing C# Silverlight application that just takes some input and echos it back, I'll extend it to run the code through IronRuby and print the result. First, open the solution, and hit F5 to see that the app just echos what you type in the grey area. This requires you to have installed the Silverlight Tools.

image

Now add references to the DLR and IronRuby (in the Dependencies folder):

image

Let's write a little wrapper class run Ruby code. Open App.xaml.cs and add the following class to the SilverlightDLRDemo namespace:

class RubyEngine {
  private ScriptEngine _engine;

  public RubyEngine() {
    var runtime = new ScriptRuntime(
      DynamicApplication.CreateRuntimeSetup()
    );
    _engine = Ruby.GetEngine(runtime);
  }

  public object Execute(string code) {
    return _engine.Execute(code);
  }
}

Note: this exact code won't work on the Desktop; you'd have to just give the ScriptRuntime constructor no parameters. Here I use the DynamicApplication.CreateRuntimeSetup() to use the same ScriptRuntimeSetup object that Microsoft.Scripting.Silverlight uses, which knows how to map File system access to the XAP file, which is useful for dynamic languages to depend on other files. Of course, it's your decision to allow this or not.

You'll also need to add the following "using" statements:

using Microsoft.Scripting.Hosting;
using IronRuby;
using Microsoft.Scripting.Silverlight;

And that's it! That's all we need to run IronRuby code. Now let's hook it up to the page. Open Page.xaml.cs and add an instance variable to the Page class, and initialize it in the Page constructor:

// add to Page class
private RubyEngine _ruby;

// add to Page constructor
_ruby = new RubyEngine();

Lastly, replace the "Result.Text = ..." line with this, which prints the typed code, and then the result computed by the RubyEngine wrapper we just wrote:

Result.Text = "\n\n" + 
  ">> " + Code.Text + "\n" +
  (_ruby.Execute(Code.Text).ToString()) + 
  Result.Text;

Now hit F5 again, and type some Ruby into the TextBox, hit enter, and boom, you're C# Silverlight application is running IronRuby code.

image

In fact, this is exactly how AgDLR, aka the dynamic language integration with Silverlight, works -- a C# application (Microsoft.Scripting.Silverlight.dll) which hosts the DLR and runs a script file (app.rb or app.py). Take a look for yourself.

I hope that shows you how easy it is to host the DLR from a C# Silverlight application, and think twice when writing those complex rule engines. =)

comments powered by Disqus