【IronRuby】细谈Ironruby与.NET的互操作性

作者: Ray Linn   最后更新:2010/07/19

引用.NET的Assembly
除了我们前面提到的require <PartialName> 和require <Strong name>外,Ironruby 1.0发布的时候,还提供了一个新的函数load_assembly,这个函数的参数为Assembly的名称,在内部,load_assembly会先调用Assembly.Load,如果找不到这个Assembly,那就再调用Assembly.LoadWithPartialName.它也支持require的两种调用方法。除此之外,load_assembly还可以接受第二个参数,指明只引用该Assembly下的某个名称空间,比如:
load_assembly 'IronRuby.Libraries', 'IronRuby.StandardLibrary.StringIO' 


名称空间namespace
当装配件被加载之后,它的顶层名称空间和类在ironruby内是可见的。比如下面这个例子
namespace Models {   
  public class Person {   
    private string name;   
    public Person(string name) {   
      this.name = name;   
    }   
    public string Name {    
      get {   
        return name;   
      }   
    }   
  }   

上面C#代码的名称空间“Models”与普通的ruby模块一样可被存取:
>>> require 'models'  
=> true  
>>> Models   
=> Models   
>>> Models.class  
=> Module

需要注意几点:
1.不可用小写的名称空间:Ruby常量要求使用大写开头的名字,所以名称空间必须遵循Ironruby的要求。
2.不可用“空”的名称空间: 对IronRuby来说,名称空间不能为空。而且由于CLR的名称空间只在有可访问的子类时才存在,因此假如名称空间的所有子类都是私有的,IronRuby 将无法访问该名称空间。所以名称空间内至少要有一个公共的可访问类。

因为名称空间被视为Ironruby的普通模块,所以它和其他ruby模块一样,可以被mixin.

class MyApp
  include "models"
  .....
end


使用C#的类

CLR中的类被视为普通的ruby类,这会为Ruby增加许多很有趣的特性。

1. Ruby中的泛型。
泛型一直被视为减少代码错误的一种有效方式,CLR提供了完美的“膨胀法”的泛型实现,因此在ironruby中使用CLR的泛型集合,取代原有的ruby实现,不失为提高动态语言代码质量的一种方法。
#使用CLR中的泛型
dict = System::Collections::Generic::Dictionary[String, Array].new  
#实际:System.Collections.Generic.Dictionary`2[IronRuby.Builtins.MutableString,IronRuby.Builtins.RubyArray]   
dict['foo'] = [1,2,3]
#可以使用所有的ruby方法
dic['foo'].map{|x|x+1}
#下面代码会抛出异常
dict[23] = '34' 
dict[23] = [4,5,6]   


2. Ruby中的GUI
Ruby中的类可以继承CLR中的类,因此可以使用CLR的WinForm为Ruby扩展出GUI而不需要类似Shoes之类的Ruby框架
require "System.Windows.Forms"  
include System::Windows::Forms   
class RForm < Form   
end  
f = RForm.new  


3.Reopen
如果想扩展CLR中的类,比如增加一个属性,有时候不需要大费周折去创建子类继承父类。CLR中的类一样可以被打开添加属性或者方法
class Models::Person   
  attr_reader :age  
  class << self  
    alias super_new new  
    def new(name, age)   
      instance = super_new(name)   
      instance.instance_variable_set(:"@age", age)   
      instance   
    end  
  end  
end  
  
Person.new("Jimmy", 25)  

方法

方法里值得一提的是,有些.NET方法带有out修饰,比如:
public string Foo(int i, out int j, out int k);  


该方法等价于:
return_value, j, k = Foo(5)


同样带有ref修饰的:
bool Foo(string a, out string b, string c, ref string d, string e, out string f);

等价于
return_value, b_out, d_out, f_out = foo('a_in ', 'c_in ', 'd_in', 'e_in ')


由于.NET里许多类被映射成Ruby的类,在许多时候可能会出现语义不清的状态,比如.NET和Ruby的String类,都带有replace方法,因此Ironruby也提供了一些方法,用于澄清语义。

to_clr_type:返回CLR里的实际类型
clr_member:指明调用CLR里的方法、属性或者字段,如System::String.new("a").clr_member(:Replace).call("a", "b")
clr_ctor: 某些类比如Thread被映射成IronRuby的类,clr_ctor可以让你指明调用原来.NET类的构造函数。
to_clr_string:由于CLR的String和Ruby的String不是同一个类,这个方法会返回CLR的String类型。

枚举
Enum在ironruby中被视为普通的类,可以直接被使用
require 'System.Windows.Forms'  
include System::Windows::Forms      
System::Enum.GetNames(AnchorStyles.to_clr_type)   
AnchorStyles.bottom | AnchorStyles.left


事件
在Ironruby中响应CLR中的事件有好几种方法:

1.最基础的方法,使用代码块(Block)
require "System.Windows.Forms"  
button = System::Windows::Forms::Button.new  
button.click { |sender, e| puts "Click!" }   
button.perform_click   


2.使用Proc对象,这个方法在必要事可以移除响应代码。
require "System.Windows.Forms"  
button = System::Windows::Forms::Button.new  
on_click = proc { |sender, e| puts "Click!" }   
button.click(&on_click)   
button.perform_click   
button.click.remove(on_click)   
button.perform_click   


我们陈述了一些Ironruby和CLR互动的一些细节问题,这些是Ironruby有别于其他ruby实现的方面,体现了基于CLR实现Ruby的许多优点。值得一提的是,Ironruby是遵循Ruby规范的实现,大部分Ruby代码都可以在上面无缝运行,比如rails。

总结一下Ironruby和CLR通讯需要注意的一些问题:

1.CLR的名称空间和接口必须首字大写,以便映射到ruby的模块。
2.CLR的类必须首字大写以便映射成Ruby类。
3.CLR的方法可以按原有的方法名调用,也可以用ruby风格的方法名调用,即“骆驼式命名法”或 "Mangling命名法"皆可。
4.CLR的虚方法可以在Ironruby用上述二种命名法重写。

你可能感兴趣的:(.net,windows,Ruby,Rails,WinForm)