¿Hay alguna manera de establecer propiedades en Ironruby similar a la sintaxis de inicializador de objeto C#?
Pregunta
Estoy usando Ironruby para hacer algunos secuencias de comandos en mi aplicación.
Tengo muchos comandos (objetos CLR) que necesito crear y ejecutar, pero la mayoría de los comandos necesitan propiedades establecidas en ellos y quiero evitar tener que asignar el comando a una variable solo para poder establecer las propiedades.
¿Hay alguna forma de hacerlo como el objeto C#? Sintaxis inicializadora?
Solución
No existe una forma incorporada de configurar propiedades al construir objetos CLR, ya que no es una característica de Ruby. Sin embargo, aunque Python tampoco es compatible con esto, IronPython lo admite permitiendo que los parámetros nombrados se suministren a los constructores. Dado que Ruby no admite parámetros con nombre, no queríamos hacer cumplir un patrón de parámetros con nombre, ya sea un Hash
como el último argumento, o un bloque que es instance_eval
'D contra el objeto de construcción, o algo más que la gente se ocurra.
Dicho esto, ambas estrategias de implementación de inicializadores de objetos se pueden escribir en Ruby puro sin ningún apoyo especial en Ironruby. Describiré ambos mencionados anteriormente, pero no dude en experimentar si no son exactamente la sintaxis que estaba buscando.
Suponiendo la siguiente clase CLR (escrita en C#):
namespace TestLib {
public class TestObj1 {
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
}
Puede imaginar las propiedades de inicialización con un bloque pasado al constructor:
testobj = TestObj1.new do
self.prop1 = "Prop1 Value"
self.prop2 = "Prop2 Value"
end
Y así es como podrías anular el TestObj1.new
Método para admitir eso:
class TestObj1
def self.new(*args, &block)
obj = super(*args)
obj.instance_eval &block
obj
end
end
Dado que esto en realidad eval
S El bloque contra el objeto recién creado, puede ejecutar cualquier código Ruby dentro del bloque. Este patrón es popular al crear DSL y más API naturales en Ruby.
O, si prefiere usar Ruby's Lenient Hash
Sintaxis en argumentos de método:
testobj = TestObj1.new :prop1 => "Prop1 value", :prop2 => "Prop2 value"
Entonces así es como podrías anular el .new
método:
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
los Hash
La opción es definitivamente un poco más complicada, pero un poco más desempeñada (como evita eval
) y es un patrón más común en Ruby para exponer los parámetros nombrados.