Есть ли способ установить свойства в IronRuby аналогично синтаксису инициализатора объекта C #? - PullRequest
1 голос
/ 16 февраля 2012

Я использую IronRuby для выполнения некоторых сценариев в своем приложении.

У меня много команд (объектов CLR), которые мне нужно создавать и выполнять, но большинству команд нужны свойства, установленные на них, и я хочучтобы избежать необходимости назначать команду для переменной, просто чтобы я мог установить свойства.

Есть ли способ сделать это, как объект C # синтаксис инициализатора ?

1 Ответ

3 голосов
/ 17 февраля 2012

Нет встроенного способа установки свойств при создании объектов CLR, так как это не является особенностью самого Ruby. Однако, хотя Python и этого не поддерживает, IronPython поддерживает это, позволяя указывать именованные параметры конструкторам . Поскольку 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 внутри блока. Этот шаблон популярен при создании DSL и более естественных API в Ruby.

Или, если вы предпочитаете использовать синтаксис 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 для представления именованных параметров.

...