有没有办法在IronRuby中设置属性类似于C#对象初始化程序语法?

时间:2012-02-16 02:00:23

标签: .net ruby ironruby

我正在使用IronRuby在我的应用程序中编写脚本。

我有很多命令(CLR对象)我需要创建和执行,但是大多数命令都需要在它们上设置属性,我想避免必须将命令分配给变量,这样我才能设置属性。

有没有办法像C#对象initializer syntax那样做?

1 个答案:

答案 0 :(得分:3)

构造CLR对象时没有内置的设置属性的方法,因为它不是Ruby本身的功能。但是,虽然Python也不支持这一点,IronPython does support it by allowing named parameters to be supplied to constructors。由于Ruby不支持命名参数,因此我们不希望强制执行命名参数模式,无论是Hash作为最后一个参数,还是对instance_eval'反对构造对象的块,或者人们想出的其他东西。

话虽这么说,实现对象初始化器的两种策略都可以用纯Ruby编写,而不需要IronRuby中的任何特殊支持。我将描述上面列出的两个,但如果它们不是您正在寻找的语法,请随时进行试验。

假设以下CLR类(用C#编写):

namespace TestLib {
  public class TestObj1 {
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
  }
}

您可以想象使用传递给构造函数的块初始化属性:

testobj = TestObj1.new do
  self.prop1 = "Prop1 Value"
  self.prop2 = "Prop2 Value"
end

以下是您可以覆盖TestObj1.new方法以支持该方法的方法:

class TestObj1
  def self.new(*args, &block)
    obj = super(*args)
    obj.instance_eval &block
    obj
  end
end

由于实际上eval是针对新创建的对象的块,因此您可以在块内执行任何Ruby代码。在Ruby中创建DSL和更自然的API时,这种模式很流行。

或者,如果您更喜欢在方法参数中使用Ruby的宽松Hash语法:

testobj = TestObj1.new :prop1 => "Prop1 value", :prop2 => "Prop2 value"

然后,您可以覆盖.new方法:

class TestObj1
  def self.new(*args)
    last_arg = args[-1]
    if last_arg.kind_of?(Hash)
      first_args = args[0..-2]
      obj = super(*first_args)
      last_arg.each do |prop, val|
        obj.send("#{prop}=", val)
      end
      return obj
    end
    super(*args)
  end
end

Hash选项肯定有点复杂,但性能更高(因为它避免了eval),并且是Ruby中更常见的模式,用于公开命名参数。