本文章是由機器翻譯。

行動運算

在 Windows Phone 7 上運用 IronRuby

Shay Friedman

下載代碼示例

幾年前,我是一個不折不扣的 .NET 迷。我對其他的開發領域毫無興趣,整個人都沉醉于自己的封閉世界中。隨後,我又誤打誤撞地學習了 Ruby,那種體驗簡直不可思議。那種利用語言的內置功能來完成工作的方式深深地吸引了我。

還有的就是,您可以讓一個人領略 .NET 世界外部的事物,但 .NET 將永遠深深地紮根在那個人的心裡。因此,當我一聽說 Microsoft 要在 Microsoft .NET Framework 上開發一種名為 IronRuby 的 Ruby 語言的實現時,心裡十分激動,然後便一頭鑽了進去。

現在,有了 IronRuby,.NET 世界和 Ruby 世界之間就架起了一座彼此連接的橋樑。這可以使無限種新可能變為現實,這種連接的好處超乎想像。

在本文中,我將向您介紹其中一種無論對於 .NET Framework 開發人員還是 Ruby 開發人員都很重要的好處,那就是您可以在 Windows Phone 7 上使用 IronRuby。

什麼是 IronRuby?

2006 年,Microsoft 宣佈開發 IronRuby。花三年以上開發,並在四月份 IronRuby 小組宣佈 IronRuby 第一個穩定的版本:1.0 版。

IronRuby 支援整個的功能集的注音的語言與唯一的加法:注音的程式碼和.NET Framework 程式碼之間的整合。該集成是完全無縫的,唯一需要做的就是將 .NET Framework 程式集載入到 Ruby 上下文中。例如,下麵這段 IronRuby 代碼首先載入 System.Windows.Forms 程式集,然後再利用其類:

require 'System.Windows.Forms'

include System::Windows::Forms

form = Form.
new
form.height = 200
form.width = 400
form.text = "IronRuby Window"
form.show_dialog

能夠實現該集成可能要歸功於動態語言運行時 (DLR),這是一個添加到 .NET Framework 基礎結構中的層,用於為在該框架上編寫的動態語言提供公共服務。 DLR 是在 CLR 基礎上編寫而成的,可以使在 .NET 上實現動態語言變得更加容易。 這是最近我們看到 .NET Framework 動態語言(包括 IronRuby、IronPython、IronJS、Nua、ClojureCLR 等等)不斷興起的主要原因之一。

IronRuby 的主要功能

Ruby 是一種動態語言,IronRuby 也是如此。 這就是說,在沒有編譯器的情況下,對於靜態語言中在編譯和生成期間完成的大多數操作,在運行時都能夠完成。 這種行為可以提供當前大多數靜態語言中難以或不可能實現的各種功能。

與 .NET Framework 物件的互通性。Ruby 語言包含多種實現:MRI(即最初的實現)、Jruby、Rubinius、MacRub、IronRuby 等等。 IronRuby 之所以能夠脫穎而出,要歸功於其能夠與 .NET Framework 物件方便地進行交互。 這種互通性是雙向的,即 .NET Framework 物件可以在 IronRuby 代碼中使用,IronRuby 物件也可以在 .NET Framework 代碼中使用。

動態類型化。IronRuby 變數類型可以在運行時計算得出,因此無需在代碼中指定變數的類型。 但是,這並不表示 IronRuby 沒有類型。 IronRuby 包含類型,而且和靜態語言中的類型一樣,每種類型都有其各自的規則。 以下代碼示例用幾個簡單的步驟說明了動態類型化機制:

# 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"

互動式主控台。與 Windows 命令提示符類似,互動式主控台也是一種可以檢索 IronRuby 代碼並立即執行該代碼的應用程式。這種執行流也稱為讀取-求值-輸出-迴圈 (REPL)。您可以定義變數、方法甚至類,載入 IronRuby 檔或 .NET Framework 程式集,並立即使用它們。例如,圖 1 中顯示一個簡單的主控台會話,該會話中創建了一個類並立即使用該類。

圖 1 使用 IronRuby 主控台

鴨子類型化。IronRuby 是一種物件導向的語言。正如大家在物件導向的語言中所期待的那樣,IronRuby 支援類、繼承、封裝和存取控制。但是,與許多靜態語言一樣,它不支援介面和抽象類別。

不過,這並不是該語言的設計缺陷。有了動態類型化功能,聲明介面或抽象類別之類的代碼約定顯得多此一舉。唯一與物件有關的事項是是否定義了特定的方法;如果已定義,則無需進行標記。這就是通常所說的鴨子類型化 - 如果某個類型的叫聲像鴨子,游泳姿勢也像鴨子,那麼它就是一隻鴨子,無需進行標記即可將其視為一隻鴨子。

例如,圖 2 中的代碼示例包含兩個類,這些類包含一個名為 say_hi 的方法以及另一個名為 introduce 的常規方法,後者可以檢索一個物件並執行其 say_hi 方法。(請注意,這裡不存在介面或其他標記機制。)

图 2 鸭子类型化示例

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!"

元程式設計。IronRuby 提供了強大的元程式設計功能。 元程式設計是一種可在運行時添加、更改甚至刪除方法的方式。 例如,可以向類中添加方法、寫入定義其他方法的方法或刪除現有類中的方法定義。 图 3 向類中添加了一個方法,添加的方法將反映到該類的所有當前實例和將來實例中。

圖 3 在聲明類後向該類中添加方法

# 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"

此外,還有一些特殊的方法可用於捕獲對未定義的方法或常量的調用。 使用這些方法可以輕鬆地支援 find_by_[列名稱] 之類的動態方法名稱,其中 [列名稱] 可以替換為 find_by_namefind_by_cityfind_by_zipcode 之類的任何值。

RubyGems。Ruby 語言功能再強大,如果沒有可以與其一起安裝和使用的外部庫,也不會取得如此巨大的成功。

安裝 Ruby 庫的主要方法是通過 RubyGems 系統。 這是一種套裝程式管理器,可以説明分發和安裝稱為 gem 的 Ruby 庫。 有數千種免費的 gem 可以使用,幾乎涵蓋了包括測試框架、稅率計算庫以及 Web 開發框架等在內的所有程式設計方面和任務。

您應該會注意到某些 RubyGems 依賴于 C 庫。 這些 gem 無法在當前版本的 IronRuby 上運行,除非將 C 庫移植到 Ruby 或 C# 平臺上。

社区。IronRuby 的其中一個最大好處就是您可以訪問 Ruby 社區。 該社區包含遍佈于眾多論壇、郵寄清單、聊天室和博客中的寶貴內容,這些內容是由許多樂於助人解決任何問題的使用者提供的。 不要猶豫,趕快利用這些資源吧,它們真的非常有用。

IronRuby 和 Silverlight

Silverlight 2 引入新的和重要功能:DLR 語言的支援。 這樣一來,開發人員就可以將 IronRuby 用於 Silverlight 應用程式,既可以將它融入到應用程式中,也可以使用它來編寫整個 Silverlight 應用程式。

且慢,Silverlight 可以在 Windows Phone 7 上運行,對吧? 當然可以。

Windows Phone 7

萬眾期待的 Windows Phone 7 是 Microsoft 的下一代移動平臺,它是智慧手機行業的一項創新性突破。 除了標準的多點觸控功能和炫目的新 UI 之外,從開發人員的角度來看,Windows Phone 7 的最大新聞莫過於它是在 Silverlight 平臺上開發的。

正是歸功於 Microsoft 這一利用成熟技術的明智之舉,廣大開發人員只需輕鬆簡單地學習一下,就可以創建移動應用程式了。

由於 DLR 語言可以在 Silverlight 環境中運行,因此您可以充分利用 IronRuby,使用它來編寫 Windows Phone 7 應用程式。

不過,有一些限制需要注意。 Windows Phone 7 自帶的 .NET Compact Framework 是 .NET Framework 的子集。 Compact Framework 專為移動應用程式和嵌入式應用程式而設計,包含完整 .NET Framework 的大約 30% 功能。 因此,它缺失了許多類,這會影響 IronRuby 的運行。

Reflection.Emit 命名空間是影響 IronRuby 的主要缺失功能。 IronRuby 使用此功能來動態地編譯代碼,以使應用程式更快地運行。 但是,它只屬於性能上的優化,並不是運行簡單腳本和應用程式所必備的元件。

另一個限制與新 Windows Phone 7 應用程式的創建方式有關。 這類應用程式只能通過 Visual Studio 並使用 C# 來創建。 這一要求迫使開發人員不得不使用 C# 編寫代碼來初始化 IronRuby 代碼。

最後一個重要限制是 RubyGems 無法在 Windows Phone 7 上運行。 因此,要使用 gem,必須和任何其他 IronRuby 代碼檔一樣,先將其代碼檔包含在應用程式檔案中,然後再使用這些檔。

在 Windows Phone 7 上構建簡單的 IronRuby 應用程式

要開發 IronRuby 驅動的 Windows Phone 7 應用程式,需要先安裝 Windows Phone 7 開發人員工具,這些工具可從 developer.windowsphone.com 上進行下載。

安裝這些工具之後,請打開 Visual Studio,然後轉到“檔”|“新建”|“專案”。 在“新建專案”對話方塊中,選擇“Silverlight for Windows Phone”類別,然後選擇“Windows Phone 應用程式”專案範本。 為該專案命名,然後繼續操作。

新專案一打開,您就會看到已自動創建了一個簡單的 XAML 檔。 請注意,XAML 通常是 Silverlight 必需的,並不依賴于語言。 因此,即使應用程式碼將使用 IronRuby 來編寫,也必須使用 XAML 來創建 UI。 在這個簡單的應用程式中,預設的 XAML 檔已經夠用,因此這裡無需做任何更改。

這個簡單的應用程式中,最值得關注的部分是代碼。 不過,在對此進行深入探討之前,我們需要添加對 IronRuby 和 DLR 程式集的引用。 這些程式集並不是常規的程式集,我們需要的是適用于 Windows Phone 7 的程式集,它們可以從 ironruby.codeplex.com/releases/view/43540#DownloadId=133276 上獲取。 可以在下載的套裝程式的 silverlight/bin 資料夾中找到所需的程式集。

接下來,我們需要編寫 IronRuby 代碼。 向應用程式中添加一個新的文字檔,然後將其命名為 MainPage.rb。 此外,為了便於部署到手機中,請打開此檔的屬性,然後將“生成操作”屬性更改為“嵌入的資源”。

接下來,將圖 4 中的代碼複製到該檔中。

圖 4 要在 Windows Phone 7 上運行的 IronRuby 代碼檔

# 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)

图 4 中的 IronRuby 代碼非常簡單易懂;我們設置了標題,創建了一個文字區塊,其中包含一些文本,並將其添加到頁面中。 請注意,您可以在上面提及的 Windows Phone 環境運行限制下,使用 Ruby 語言中的所有功能(這裡就不演示了),例如類、元程式設計和庫。

現在,剩下的任務就是實際執行 IronRuby 代碼了。 要在應用程式載入時執行該代碼,請將圖 5 中的代碼添加到位於 MainPage.xaml.cs 檔內的 MainPage 類構造函數中。

圖 5 添加代碼以通過類構造函數執行 IronRuby 代碼

// 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);

图 5 中的代碼十分簡短,完美地演示了通過 C# 代碼運行 IronRuby 代碼有多麼容易。

另外,請務必將以下 using 語句添加到該類中:

using System.Reflection;
using System.IO;
using Microsoft.Scripting.Hosting;
using IronRuby;

图 5 中的第三行代碼可以將 System.Windows.Media 程式集載入到 IronRuby 上下文中,從而使該代碼可以與該程式集的類和枚舉進行交互操作。

下一行允許 IronRuby 代碼訪問當前的 Silverlight 頁面。該行代碼通過名為 Phone 的常量向 IronRuby 代碼公開當前實例 (this)。

其餘的代碼從嵌入的檔(請注意,應用程式的命名空間將添加到檔案名中,因此 MainPage.rb 變成了 SampleWPApp.MainPage.rb)中讀取 IronRuby 代碼,然後使用引擎實例來執行該代碼。

就是這樣。我們已經創建了一個應用程式,該應用程式載入後,會運行 IronRuby,而該代碼將更改標題並向 Silverlight 頁面添加一個文字區塊。剩下要做的所有事情就是運行該應用程式,運行結果如圖 6 所示。

圖 6 Windows Phone 7 上運行的 IronRuby 驅動的應用程式

每時每刻都在完善

即使在 Windows Phone 7 上使用 IronRuby 的工作流還並不完善,而且您需要注意各種限制,但這只是個起步而已。IronRuby 和 Windows Phone 7 平臺都是嶄新的,它們時刻都在不斷完善。

二者的結合同時給 .NET Framework 開發人員和 Ruby 開發人員展現了廣大的前景。現在,.NET 開發人員在編寫 Windows Phone 7 應用程式時,可以充分利用 Ruby 語言無以倫比的功能,例如,將 IronRuby 主控台融入到其應用程式中或提供可擴展性功能。而另一方面,Ruby 開發人員也可以史無前例地使用自己的語言來編寫移動應用程式。

毫無疑問,一個充滿大量機遇和無限可能的嶄新世界已經誕生。而且一切盡在您的掌控之中。

Shay Friedman 是一位 Microsoft Visual C#/IronRuby MVP,也是 《IronRuby Unleashed》 (Sams 出版,2010 年)一書的作者。.他現在擔任 Sela Group 的動態語言主管,負責全球範圍的課程諮詢和開設工作。可以在 IronShay.com 上閱讀他的博客文章。

*衷心感謝以下技術專家對本文的審閱:*Tomas Matousek