0

I have an application that implements several objects in C# and then expects those objects to be usable from IronRuby by adding them to a Microsoft.Scripting.Hosting.ScriptScope. This works for the most part: I've learned how to implement the various members of DynamicObject to make things act correctly. But how do I make an object compatible with Ruby's for loops?

My C# object looks like this:

 public class TrialObject : DynamicObject, IEnumerable<int> {
    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
       if (indexes.Length != 1) return base.TryGetIndex(binder, indexes, out result);
       try {
          var index = (int)indexes[0];
          result = index;
          return true;
       } catch { return base.TryGetIndex(binder, indexes, out result); }
    }

    public int Length { get { return 3; } }

    public IEnumerator<int> GetEnumerator() {
       yield return 0;
       yield return 1;
       yield return 2;
    }

    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
 }

Then I try to use the object from ruby, like so.

trial.Length                   # returns 3
trial[0]                       # returns 0
trial[2]                       # returns 2
for t in trial do <stuff>; end #error: no block given

How do I adjust the trial object to allow it to work in a for loop? I know I could use "i in 0..trial.Length-1" as a hack around, but I'd rather fix the problem than introduce a hack.

benjamin.popp
  • 547
  • 1
  • 6
  • 20

1 Answers1

0

After some trial and error, I learned that I could get the desired effect by adding an "each" method to my class.

public class TrialObject : DynamicObject, IEnumerable<int> {
   ...
   public IEnumerable<BuildableObject> each() { return this; }
   ...
}

It seems as if ironruby uses the "each" method to implement its for. So by adding an each method, I can get this dynamic object to act like the IEnumerable it's trying to be.

benjamin.popp
  • 547
  • 1
  • 6
  • 20