On Jun 23, 2011, at 11:45 AM, Rob Britton wrote:
> I'm attempting to write a method in C# that is called by IronRuby to
> speed up an existing script, and I call it like this:
> 
>  foo :limit => 5, :offset => 10
> 
> How would I go about accessing these objects from C#? I'm trying
> something like this:
> 
> void foo(Hash options){
>  int limit = (int)options[new RubySymbol("limit")];
>  ...
> }
> 
> However this doesn't work since RubySymbols constructor is private.
> How would I go about getting the objects within the hash?


Rob, it's best to avoid depending on IronRuby built-in types in your .NET API 
unless you absolutely need to, as well as always having your .NET API's 
arguments be interface types, so both Ruby and .NET can call into them. If you 
did this:

    // C#
    public class MyClass {
        public void Foo(IDictionary args) {}
    }

You can still call it from Ruby:

    my_class.foo :limit => 5, :offset => 10

As for indexing, you can copy the provided Hash into a Dictionary<string, 
object> to provide string-based indexing:

    void Foo(IDictionary args) {
        var dict = new Dictionary<string, object>();
        foreach (DictionaryEntry a in args) dict[a.Key.ToString()] = a.Value;
        var limit = dict["limit"];
        var offset = dict["offset"];
        // do your stuff
    }


Another option (which I like more) is to write a Ruby wrapper around it to 
convert the keys to CLR strings:

    require 'MyClass' # load above assembly
    class MyClass # monkey-patch above .NET class
        alias :orig_foo :foo
        def foo(args)
            orig_foo args.inject({}){|i,(j,k)| i[j.to_clr_string] = k; i }
        end
    end

Then you wouldn't have to do the conversion in C#:

    void Foo(IDictionary dict) {
        var limit = dict["limit"];
        var offset = dict["offset"];
        // do your stuff
    }

I like the latter option best because you do what Ruby needs in Ruby; your .NET 
code assumes it's getting a CLR string rather than forcing it to be. However, 
it's not ideal as you have to copy the dictionary in both cases, but for an 
argument hash it's very unlikely to become an issue.

You'll notice that if you a .NET method that accepts a string, you can pass it 
a Ruby symbol; we do the conversion between Ruby symbols and .NET strings. 
However, we don't do conversions between generic arguments, especially with a 
Ruby Hash, were they keys could be different types. But we could convert a Hash 
to a statically typed Dictionary if all they keys are the same type; if you 
feel strongly about this please open a bug.

~Jimmy
_______________________________________________
Ironruby-core mailing list
Ironruby-core@rubyforge.org
http://rubyforge.org/mailman/listinfo/ironruby-core

Reply via email to