Going Places - IronRuby on Windows Phone 7
By Shay Friedman | September 2010
A few years ago, I was a 100 percent .NET guy. I didn’t have a clue about the rest of the development world, and I was quite happy in my own bubble. Then, kind of by mistake, I learned Ruby, and the experience was jaw-dropping. The way things get done using the language’s built-in features was striking to me.
Still, you can take the person out of the .NET world, but you can’t take the .NET world out of the person. So as soon as I heard Microsoft was developing an implementation of the Ruby language—called IronRuby—on top of the Microsoft .NET Framework, I got pretty excited and dove right into it.
With IronRuby, the .NET world and the Ruby world are now connected. This enables endless new possibilities, and the benefits of such a connection are nothing short of phenomenal.
In this article, I’m going to tell you about one of the benefits that’s important to both .NET Framework and Ruby developers—you can use IronRuby on Windows Phone 7.
What Is IronRuby?
In 2006, Microsoft announced the development of IronRuby. It took more than three years to develop, and in April the IronRuby team announced the first stable version of IronRuby: version 1.0.
IronRuby supports the entire feature set of the Ruby language with a unique addition: integration between Ruby code and .NET Framework code. This integration is fairly seamless and requires little more than loading a .NET Framework assembly to the Ruby context. For example, this IronRuby code loads the System.Windows.Forms assembly and takes advantage of its classes:
require 'System.Windows.Forms' include System::Windows::Forms form = Form.new form.height = 200 form.width = 400 form.text = "IronRuby Window" form.show_dialog
This integration is possible thanks to the Dynamic Language Runtime (DLR), a layer added to the .NET Framework infrastructure to provide common services to dynamic languages written on top of the framework. The DLR is written on top of the CLR and makes it much easier to implement dynamic languages on top of .NET. This is one of the main reasons for the rise of .NET Framework dynamic languages we’ve seen lately, including IronRuby, IronPython, IronJS, Nua, ClojureCLR and others.
Key Features of IronRuby
Ruby is a dynamic language and so is IronRuby. This means there’s no compiler at hand, and most of the operations done during compilation and build time in static languages are done during run time. This behavior provides a variety of features that are difficult or impossible to achieve in most current static languages.
Interoperability with .NET Framework Objects The Ruby language has various implementations: MRI (which is the original one), JRuby, Rubinius, MacRub, IronRuby and others. What makes IronRuby stand out from the crowd is its ability to conveniently interact with .NET Framework objects. That interoperability goes both ways—.NET Framework objects are available from IronRuby code and IronRuby objects are available from .NET Framework code.
Dynamic Typing IronRuby variable types are calculated during run time, so there’s no need to specify the types in your code. However, that doesn’t mean that IronRuby doesn’t have types. It does, and every type has its own rules, just like types in static languages. This code sample demonstrates the dynamic typing mechanism in a few simple steps:
# Declaring a numeric variable a = 1 # The variable is of a numeric type # and therefore numeric operations are available a = a * 2 + 8 / 4 # The next line will raise an exception # because it is not possible to add a string to a number a = a + "hello" # However, the next line is entirely legit and will result # in changing the variable type to String a = "Hello"
The Interactive Console Similar to the Windows command prompt, the interactive console is an application that retrieves IronRuby code and immediately executes it. The execution flow is also known as Read-Evaluate-Print-Loop (REPL). You can define variables, methods and even classes, load IronRuby files or .NET Framework assemblies and use them instantly. For example, Figure 1shows a simple console session that creates a class and immediately uses it.
Figure 1 Using the IronRuby Console
Duck Typing IronRuby is an object-oriented language. It supports classes, inheritance, encapsulation and access control, like you’d expect from an object-oriented language. However, it doesn’t support interfaces or abstract classes, like many static languages do.
This isn’t a flaw in the language design, though. With dynamic typing, declaring code contracts such as interfaces or abstract classes becomes redundant. The only thing that matters about an object is whether it defines a specific method or not, and there’s no need to mark it when it does. This is known as duck typing—if it quacks like a duck and it swims like a duck, it’s a duck, and there’s no need to stamp it to consider it as a duck.
For example, the code sample in Figure 2 contains two classes with a method named say_hi and another general method named introduce that retrieves an object and executes its say_himethod.(Notice the absence of interfaces or other marking mechanisms.)
class Human def say_hi puts "Hi!" end end class Duck def say_hi puts "Quack!" end end def introduce(obj) obj.say_hi end human = Human.new duck = Duck.new introduce(human) # prints "Hi!" introduce(duck) # prints "Quack!"
Metaprogramming IronRuby comes with powerful metaprogramming capabilities. Metaprogramming is a way to add, change and even remove methods during run time. For example, it’s possible to add methods to a class, write methods that define other methods or remove method definitions from an existing class. Figure 3 adds a method to a class that’s reflected to all current and future instances of that class.
# Creating a class with no methods class Demo end # Creating an instance of class Demo d = Demo.new # Opening the class and adding a new method - hello_world class Demo def hello_world puts "hello world" end end # Using the newly added method on the class instance d.hello_world # prints "hello world"
Moreover, there are special methods that can be used to catch calls to undefined methods or constants. Using these methods makes it easy to support dynamic method names such as find_by_[column name] where [column name] can be replaced with any value such as find_by_name, find_by_city or find_by_zipcode.
RubyGems The Ruby language, as powerful as it is, wouldn’t have become such a huge success without the external libraries that can be installed and used with it.
The main method of installing Ruby libraries is via the RubyGems system. It’s a package manager that helps distribute and install Ruby libraries, which are called gems. There are thousands of free gems available, covering almost every programming aspect and task, including testing frameworks, tax calculation libraries, Web development frameworks and more.
You should be aware that some RubyGems depend on C libraries. These gems can’t run on the current version of IronRuby unless the C libraries are ported to plain Ruby or to C#.
The Community One of the best things about IronRuby is that you get access to the Ruby community. This includes valuable content in dozens of forums, mailing lists, chat rooms and blogs provided by people who are willing to help with any question. Don’t hesitate to take advantage of these resources; they’re extremely useful.
IronRuby and Silverlight
Silverlight 2 introduced a new and important feature: support for DLR languages. As a result, developers can use IronRuby with Silverlight applications, from incorporating it in the application to writing entire Silverlight applications with it.
But wait, Silverlight is running on Windows Phone 7, right? Exactly.
Windows Phone 7
The next Microsoft mobile platform, Windows Phone 7, is expected by some to become a game-changer in the smartphone industry. Apart from the standard multi-touch capabilities and a shiny new UI, the best news about Windows Phone 7 from a developer’s perspective is that Silverlight is its development platform.
It’s a smart move by Microsoft to make use of a well-established technology, thus enabling a large number of developers to create mobile applications with an easy, almost unnoticeable, learning curve.
Because DLR languages are capable of running within the Silverlight environment, you can take advantage of IronRuby and use it to write Windows Phone 7 applications.
However, there are some limitations you should be aware of. Windows Phone 7 comes with the .NET Compact Framework, which is a subset of the .NET Framework. The Compact Framework is designed for mobile and embedded applications and contains approximately 30 percent of the full .NET Framework. Consequently, numerous classes are missing, and this affects how IronRuby works.
The main missing feature that affects IronRuby is the Reflection.Emit namespace. IronRuby uses this feature to compile code on the fly to make applications run faster. However, it’s only a performance optimization and not a component necessary for running simple scripts and applications.
Another limitation concerns the way new Windows Phone 7 applications are created. Such applications can be created only from Visual Studio and only in C#. This requirement forces developers to write code in C# that initiates the IronRuby code.
The last important limitation is that RubyGems won’t work on Windows Phone 7. Hence, to use a gem, you have to include its code files within the application files and use them as any other IronRuby code files.
Building a Simple IronRuby Application on Windows Phone 7
To start an IronRuby-driven Windows Phone 7 application, you first need to install the Windows Phone 7 Developer Tools, which can be downloaded from developer.windowsphone.com.
After the tools are installed, open Visual Studio and go to File | New | Project. In the New Project dialog select the “Silverlight for Windows Phone” category and then choose the “Windows Phone Application” project template. Name it and continue.
As soon as the new project opens, you’ll notice that a simple XAML file has been created for you. Note that XAML is required for Silverlight in general and isn’t language-dependent. Therefore, even though the application code will be written in IronRuby, you must use XAML to create the UI. In this simple application, the default XAML file is enough, so no changes need to be made here.
The interesting part of this simple application is the code. Before we dive into that, however, we need to add references to the IronRuby and DLR assemblies. These assemblies aren’t the regular ones; we need the Windows Phone 7-ready assemblies, which you can retrieve from ironruby.codeplex.com/releases/view/43540#DownloadId=133276. You’ll find the needed assemblies inside the silverlight/bin folder in the downloaded package.
Next, we need to write the IronRuby code. Add a new text file to the application and name it MainPage.rb. In addition, to ease the deployment to the phone, open the properties of this file and change the “Build Action” property to “Embedded Resource.”
Then paste the code from Figure 4 into the file.
# Include namespaces for ease of use include System::Windows::Media include System::Windows::Controls # Set the titles Phone.find_name("ApplicationTitle").text = "MSDN Magazine" Phone.find_name("PageTitle").text = "IronRuby& WP7" # Create a new text block textBlock = TextBlock.new textBlock.text = "IronRuby is running on Windows Phone 7!" textBlock.foreground = SolidColorBrush.new(Colors.Green) textBlock.font_size = 48 textBlock.text_wrapping = System::Windows::TextWrapping.Wrap # Add the text block to the page Phone.find_name("ContentGrid").children.add(textBlock)
The IronRuby code in Figure 4 is pretty straightforward; we set the titles, create a text block with some text and add it to the page. Note that you can use everything in the Ruby language (not done here), such as classes, metaprogramming and libraries, with the aforementioned limitations of running within the Windows Phone environment.
Now all that’s left is to actually execute the IronRuby code. To do so when the application loads, the code from Figure 5 should be added to the MainPage class constructor, which is located inside the MainPage.xaml.cs file.
// Allow both portrait and landscape orientations SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape; // Create an IronRuby engine and prevent compilation ScriptEngine engine = Ruby.CreateEngine(); // Load the System.Windows.Media assembly to the IronRuby context engine.Runtime.LoadAssembly(typeof(Color).Assembly); // Add a global constant named Phone, which will allow access to this class engine.Runtime.Globals.SetVariable("Phone", this); // Read the IronRuby code Assembly execAssembly = Assembly.GetExecutingAssembly(); Stream codeFile = execAssembly.GetManifestResourceStream("SampleWPApp.MainPage.rb"); string code = new StreamReader(codeFile).ReadToEnd(); // Execute the IronRuby code engine.Execute(code);
The code in Figure 5 is fairly short and gracefully demonstrates how easy it is to run IronRuby code from C# code.
In addition, make sure to add these using statements to the class:
using System.Reflection; using System.IO; using Microsoft.Scripting.Hosting; using IronRuby;
The third line of code in Figure 5 loads the System.Windows.Media assembly into the IronRuby context, which enables the code to interoperate with this assembly’s classes and enums.
The next line allows the IronRuby code to access the current Silverlight page. This line exposes the current instance (this) to the IronRuby code via a constant named Phone.
The rest of the code reads the IronRuby code from the embedded file (note that the application namespace should be added to the file name, so MainPage.rb becomes SampleWPApp.MainPage.rb) and then executes it using the engine instance.
And that’s it. We’ve created an application that, once loaded, runs IronRuby, which, in turn, changes the titles and adds a text block to the Silverlight page. All that’s left is to run the application, and the result is shown in Figure 6.
Figure 6 An IronRuby-Driven Application Running on Windows Phone 7
Getting Better All the Time
Even though the workflow isn’t perfect when using IronRuby on Windows Phone 7, and you need to keep the various limitations in mind, this is only the beginning. The IronRuby and Windows Phone 7 platforms are both new and they’re getting better all the time.
This combination opens up many possibilities, to both .NET Framework developers and Ruby developers. Now, .NET developers can take advantage of the incredible power of the Ruby language when writing Windows Phone 7 applications, such as incorporating an IronRuby console into their apps or providing extensibility capabilities. And Ruby developers, on the other end, can—for the first time—write mobile applications using their language.
This is, without a doubt, the dawn of a brave new world with a lot of opportunities and possibilities. And it’s all in the palm of your hands.
Shay Friedman is a Microsoft Visual C#/IronRuby MVP and the author of IronRuby Unleashed (Sams, 2010). He’s working as a dynamic languages leader in Sela Group where he consults and conducts courses around the world. Read his blog at IronShay.com.
Thanks to the following technical expert for reviewing this article: Tomas Matousek