我正在使用IronRuby在我的应用程序中编写脚本。
我有很多命令(CLR对象)我需要创建和执行,但是大多数命令都需要在它们上设置属性,我想避免必须将命令分配给变量,这样我才能设置属性。
有没有办法像C#对象initializer syntax那样做?
答案 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中更常见的模式,用于公开命名参数。