Great, thanks! I don''t feel strongly about it so I''ll just put
in a
little helper function to my .NET project to convert a Hash to a
Dictionary<string, object>. The monkey-patching method might not work
too well since there will be many functions that might use this
pattern, and having to monkey-patch every single one of them might get
annoying.
On Thu, Jun 23, 2011 at 2:45 PM, Jimmy Schementi <jschementi at gmail.com>
wrote:> 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 at rubyforge.org
> http://rubyforge.org/mailman/listinfo/ironruby-core
>
>