IronRuby是微软的Ruby实现,它以.NET架构良好的互动性闻名于世。Iron这个名字实际上是“Implementation running on .NET”的首字母缩写。.NET的公共语言运行时和Mono(非官方的)均能够支持IronRuby。你可以不必弄清楚某些关于动态语言运行的问题(例如在CLR之上的Ruby),这就是DLR(动态语言运行时)将要帮你解决的。DLR是微软作为在CLR之上提供动态语言支持能力的一种技术手段。
作为微软对开源软件做出的承诺中的一部分,IronRuby和DLR可以在遵循微软公用许可证(Microsoft Public License)的前提下分别从GitHub和CodePlex中获得。从设计之初,IronRuby的目标就是成为Windows平台上Ruby实现的首选,而它自然也提供了良好的兼容性和优异的性能。在撰写本文的时候,IronRuby在RubySpec的通过率已经能够达到86%。反过来让我们看看MRI,它的通过率是98%。虽然通过率尚有不足,但是从测试上来看,IronRuby的性能要比MRI 1.8优异许多(高出四倍以上),这个测试结果是Antonia Cangiano运行他的Ruby测试套件之后给出的。
不仅仅拥有良好的兼容性和优异的性能,IronRuby的杀手锏是它和.NET标准库以及.NET程序集(assembly)之间良好的互动能力。仅仅只需一条‘require’语句,你就可以在Ruby代码中使用.NET架构和类。这个重要的功能就这样“自动”地在Ruby标准库的基础上被引入到IronRuby代码中。require后面可以跟任何.NET程序集的名字。让我们在Ruby中创建一个Windows Form,来看看Ruby和.NET是如何无缝集成的:
require 'System.Windows.Forms' System::Windows::Forms::Form.new.show
运行ir(IronRuby解释器),你将会在屏幕上看到一个标准的Windows Form!虽然只是一个空的Form,但是仅仅两行代码你又能期望多少呢?这里的代码之美就在于它需要比C#或者VB用更少的代码完成相同的事情。可以想象得到,你还能够程式化地向这个新的Form中加入一些控制逻辑:
require 'System.Windows.Forms' form = System::Windows::Forms::Form.new lbl = System::Windows::Forms::Label.new lbl.text = "foo" form.controls.add(lbl) form.show
比较静态语言和动态语言的代码是非常困难的事情,但是,我们可以先看看上面的代码在C#中应该是什么样子的:
using System; using System.Windows.Forms; namespace MyWinFormsApplication { static class Program { static void Main() { Form form = new Form(); Label lbl = new Label(); lbl.Text = "foo"; form.Controls.Add(lbl); form.Show(); } } }
有一些.NET框架经验的开发者将会意识到,C#或者VB程序中的对象一旦编译之后就是作为CLR对象存在。也就是说,任何能够和.NET CLI(公共语言基础架构)良好互动的程序都可以访问这些对象。这个特点允许开发者能够应付在VB、C++或者甚至是PowerShell中的C#类和方法(反之亦然)。.NET代码不会被编译成本地代码,而是转换成为一种可以称为CIL(公共中间语言)中间语言。不幸的是,CIL是静态类型语言,不过,正如我之前在介绍中提及的那样,这就是DLR如何能够提供CLR和例如Ruby这样动态语言交互能力的关键所在。
.NET程序集的方法可以以两种形式在IronRuby中表示:熟悉的ruby小写形式(例如controls.add)和传统的C#驼峰形式(例如ToString)。由于Ruby并没有大多数.NET语言中的属性概念(CLR中是字段),所以在IronRuby中属性是以访问方法和存取方法(例如foo.bar()和foo.bar=(x))的形式存在。假设我们将以下C#命名空间和Person类编译成了一个MyClassLibrary.dll文件:
namespace MyClassLibrary { public class Person { public string Name { get; set; } public string Introduce() { return String.Format("Hi, I'm {0}", Name); } } }
下面将会演示如何在IronRuby中使用这个dll。
require 'MyClassLibrary.dll' me = MyClassLibrary::Person.new me # => MyClassLibrary.Person me.name = "Edd" me.name #=> 'Edd' me.introduce # => 'Hi, I'm Edd'
这种纯正的互动能力能够帮助开发者在一些元程序设计场合复用Ruby代码。
注意:注意大小写!如果你希望在IronRuby中使用你自己的.NET程序集,请保证你的.NET代码中的命名空间和类名使用的是正确的大写驼峰表示法。.NET类可以直接转换成Ruby类,而命名空间是以Ruby模块的形式表示,在Ruby中两者都会使用大写驼峰表示法。如果你的.NET代码中的名字不是使用的这种表示法,那么就无法将两者联系起来,从而不能在Ruby代码中使用。
元编程(Metaprogramming)的科学和艺术可以写一篇很长的文章,尤其是在Ruby中,我们可以充分享受到元编程的乐趣。就像你希望的那样,在IronRuby中,你也可以尽情地发挥自己的想象力,使用一切可以在动态语言中能够使用的东西。让我们看看如何在Ruby使用可信赖的class_eval来处理之前例子的Person类的:
require 'MyClassLibrary.dll' me = MyClassLibrary::Person.new me.name = "Edd" MyClassLibrary::Person.class_eval do define_method(:shout) do |text| "#{name} shouts: #{text.upcase}!" end end puts me.shout("Hello, world") #=> "Edd shouts: HELLO, WORLD!"
如之前例子所示,ir(IronRuby解释器)将会执行这段代码。如果你希望能够有更多证据证明IronRuby是一种“只有想不到,没有做不到”的语言,那么我们使用典型的Rails-esque作为mixin。请记住我们在这里一直使用的是使用C#编写的类。
require 'MyClassLibrary.dll' me = MyClassLibrary::Person.new module ActsAsHungry def self.included(base) puts "I'm hungry..." end def tummy_contents @tummy_contents ||= [] end def eat(foodstuff) tummy_contents << foodstuff puts "*Burp*" end end MyClassLibrary::Person.class_eval do include ActsAsHungry end me.eat("cheeseburger")
让我们回到正题。我敢打赌大部分的Ruby开发者都熟悉Rails框架,也许假设大多数都是被Rails吸引才会使用Ruby语言应该会更好些。
长话短说,IronRuby的兼容性非常优秀,你可以完美地运行你的Rails程序。但是,有些事情我不得不交代一下,否则含糊不清的语句可能会让开发者一头雾水,这是与我的初衷相违背的。我知道,当了解这些知识后,也许你会想立刻在你的Ruby应用中大量尝试这些.NET互动功能,所以我要声明,这里有些事项需要引起你的注意:
注意:MSI IronRuby安装包将会释放IronRuby到“C:/Program Files/IronRuby x.x” 下。如果你是这样安装的IronRuby,我建议最好安装到一个不会影响其他目录(不过也需要更新PATH变量),来避免脚本出现不能够解析路径名字的问题。
如上所述,IronRuby现在和Ruby 1.8.6的兼容性非常好。因此在IronRuby下运行已有的Rails应用不会有太多问题(使用ir运行你的脚本或者服务器脚本来亲自观察一下)。
如果你已经在Windows上部署相应软件,IronRuby可以通过ironruby-sqlserver gem来利用良好的.NET互动性提供SQL Server支持(也能够得到Windows集成安全机制的支持),这个gem需要一个不同于Rails自带库的DBI库,叫做ironruby-dbi,不过值得欣慰的是,ironruby-sqlserver将会检查这个库是否存在。在database.yml中的这个适配器的配置如下所示:
development: mode: ADONET adapter: sqlserver host: HOSTNAME\INSTANCE database: application_development integrated_security: true
稍稍多说一点,这其实只是在Ruby on Rails中使用IronRuby的众多优点中的冰山一角。在工业生产环境中运行这些应用是一个巨大的课题,因为选择众多:可以部署到IIS或者Windows Azure,后者是一个云平台,你可以在上面运行你的任意基于.NET的Web应用或者服务。
希望现在你已经意识到了将这些语言糅合成一门清晰的动态语言的好处,例如.NET框架下的Ruby语言。也许,你还希望知道“我可以在IronRuby中编写ASP.NET MVC应用程序吗?”或者“IronRuby和其他的技术兼容性如何?例如Silverlight或者其上层技术为浏览器外应用服务的WPF?”。如果希望寻找这些问题的答案,或者只是弄清楚你对IronRuby的一些理解,可以从IronRuby官方网站找到更多资料。
查看英文原文:What's IronRuby, and How Do I Put It on Rails?