Hey guys.
I am currently experimenting with IronRuby as an extensibility solution
for my application. However, I have hit a roadblock. What I would like
to do is call Runtime.UseFile("script.rb"), then access a global module
in the script, and instantiate a specific class in that module.
Here is the script file for reference:
module RbScriptApp
class Foo
def Bar()
return (rand(100) + 1).to_s();
end
end
end
Initially, I thought it would be as easy as typing
dynamic globals = myRuntime.Globals;
dynamic myClass = globals.RbScriptApp.Foo.@new();
myClass.Bar();
...
but I soon found out this was not the case, as the builtin RubyModule
class does not support this dynamic syntax. Is there a way around this
or is it just plain impossible? I was unable to find *any* information
about how to do this (not even about RubyModule itself!) through Google.
The exception in question is a RuntimeBinderException:
'IronRuby.Builtins.RubyModule' does not contain a definition for 'Foo'
Right now my workaround is a call to RubyModule.EnumerateConstants and
manual lookup of the class name I want, but it doesn't have the
syntactic elegance of the dynamic keyword... Any thoughts?
EDIT: Just thought I'd add, I'd like to stay away from Engine.Execute()
if at all possible, unless someone can give me a reasonable case for not
doing so.
Thanks.
on 2011-01-13 21:51
on 2011-01-15 08:55
It turns out that the problem is not accessing a module's class, but
accessing the contents of a module in a require'd file.
global.rb
require 'app'
app.rb
module RbScriptApp
class Foo
def Bar()
return (rand(100) + 1).to_s()
end
end
end
No matter what I do I can only access RbScriptApp and not Foo if I call
Runtime.UseFile("global.rb"). So far I have two other work arounds: 1.)
create wrapper methods for everything I want to access in app.rb (ugh),
or 2.) use Engine.Execute("RbScriptApp::Foo.new"). The latter is more
preferrable, I suppose, but it seems strange that I can't access Foo by
dynamic.
Any more information about this issue would be very helpful and
appreciated.
on 2011-01-15 14:08
On Jan 15, 2011, at 2:55 AM, Joshua M. wrote: > No matter what I do I can only access RbScriptApp and not Foo if I call > Runtime.UseFile("global.rb"). So far I have two other work arounds: 1.) > create wrapper methods for everything I want to access in app.rb (ugh), > or 2.) use Engine.Execute("RbScriptApp::Foo.new"). The latter is more > preferrable, I suppose, but it seems strange that I can't access Foo by > dynamic. That's how Modules work in Ruby. Just like namespaces in C#. Try adding include RbScriptApp to your global.rb file. You need to include the Module if you want to access the class without qualifying it. > Any more information about this issue would be very helpful and > appreciated. > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Ironruby-core mailing list > Ironruby-core@rubyforge.org > http://rubyforge.org/mailman/listinfo/ironruby-core -- Will Green will@hotgazpacho.org
on 2011-01-15 19:11
Another option would be
RbScriptApp.const_get("Foo")
I haven't tried that, but I think it should work. Neither solution is
indeed ideal. CLR interop with Modules isn't quite polished yet.
Tomas
on 2011-01-15 22:15
>You need to include the Module if you want to >access the class without qualifying it. I have tried this but it doesn't work (RuntimeBinderException: 'Microsoft.Scripting.Hosting.ScriptScope' does not contain a definition for 'Foo'). In my original post I had specified the fully qualified name. >RbScriptApp.const_get("Foo") InvalidOperationException: Empty scope has no global scope. >I haven't tried that, but I think it should work. Neither solution is >indeed ideal. CLR interop with Modules isn't quite polished yet. Ah, that would explain it. I guess I'll hold off on integrating IronRuby just yet. -- Thank you both for your time.
on 2011-02-24 15:41
to add directories to your search path from within C# you can do something like this: var engine = Ruby.CreateEngine(); var searchPaths = engine.GetSearchPaths().ToList(); searchPaths.Add(@"c:\code\generator\lib"); searchPaths.Add(@"C:\Ruby-ri-192\lib\ruby\1.9.1"); engine.SetSearchPaths(searchPaths); Let me know if you find out how to access classes that are within modules from C#. I'm having no luck.
on 2011-02-25 07:43
I got it working using a kind of a hack/workaround.
I know this is kind of a hack/workaround, but I managed to do it this
way:
I added the next code to the end of the ruby file:
def hack(s)
eval(s)
end
And then used it from the C# code to get the class object:
var engine = Ruby.CreateEngine();
var scope =
engine.ExecuteFile(@"c:\code\generator\lib\generator\generator_cmd_line.rb");
var genCmdLineObj = engine.Execute(String.Format("hack('{0}::{1}')",
"Generator", "CmdLine"), scope);
var cmdLineObj = engine.Operations.CreateInstance(genCmdLineObj);
var results = engine.Operations.InvokeMember(cmdLineObj, "run");
return Content(results);
Kind of a hack, but hey, it works! :)
Shay.
--------------------------------------------------------
Shay Friedman | Co-Founder @ CodeValue <http://codevalue.net/> |
C#/IronRuby MVP | Author of IronRuby Unleashed
Blog: http://IronShay.com <http://ironshay.com/> | Twitter:
http://twitter.com/ironshay
on 2011-02-25 09:38
Wouldn't this work?
dynamic globalConstants = engine.Runtime.Globals
globalConstants.MyModule.const_get('MyClass')
assuming
module MyModule
class MyClass
end
end
Haven't tried. Let me know if it works.
Tomas
From: ironruby-core-bounces@rubyforge.org
[mailto:ironruby-core-bounces@rubyforge.org] On Behalf Of Shay Friedman
Sent: Thursday, February 24, 2011 10:38 PM
To: ironruby-core@rubyforge.org
Subject: Re: [Ironruby-core] Accessing a Module's Classes from C# with
dynamic
I got it working using a kind of a hack/workaround.
I know this is kind of a hack/workaround, but I managed to do it this
way:
I added the next code to the end of the ruby file:
def hack(s)
eval(s)
end
And then used it from the C# code to get the class object:
var engine = Ruby.CreateEngine();
var scope =
engine.ExecuteFile(@"c:\code\generator\lib\generator\generator_cmd_line.rb");
var genCmdLineObj = engine.Execute(String.Format("hack('{0}::{1}')",
"Generator", "CmdLine"), scope);
var cmdLineObj = engine.Operations.CreateInstance(genCmdLineObj);
var results = engine.Operations.InvokeMember(cmdLineObj, "run");
return Content(results);
Kind of a hack, but hey, it works! :)
Shay.
--------------------------------------------------------
Shay Friedman | Co-Founder @ CodeValue<http://codevalue.net/> |
C#/IronRuby MVP | Author of IronRuby Unleashed
Blog: http://IronShay.com<http://ironshay.com/> | Twitter:
http://twitter.com/ironshay
On Thu, Feb 24, 2011 at 4:41 PM, Rob R.
<lists@ruby-forum.com<mailto:lists@ruby-forum.com>> wrote:
to add directories to your search path from within C# you can do
something like this:
var engine = Ruby.CreateEngine();
var searchPaths = engine.GetSearchPaths().ToList();
searchPaths.Add(@"c:\code\generator\lib");
searchPaths.Add(@"C:\Ruby-ri-192\lib\ruby\1.9.1");
engine.SetSearchPaths(searchPaths);
Let me know if you find out how to access classes that are within
modules from C#. I'm having no luck.
--
Posted via http://www.ruby-forum.com/.
on 2011-02-25 13:12
const_get doesn't work, but you can do globalConstants.MyModule.constants()[0] but then you get back an object which you can't initialize... Shay. On Fri, Feb 25, 2011 at 10:25 AM, Tomas Matousek <
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.