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.
After some trial and error, I learned that I could get the desired effect by adding an "each" method to my class.
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.