Hi, I am trying to create a Dsl which will have instances that live in individual Dsl .rb files and then run them from the CLR. I want to create and set the values of the Clr object in IronRuby and then somehow have access to the CLR object after the .rb Dsl instance file has run. Here is my Clr object which is very simple at the moment: namespace Horn.Core.Dsl { public class BuildMetaData : IBuildMetaData { public string Description { get; set; } } } I have the following module which I am using to specify my Dsl and which will create an instance of the BuildMetaData specified above: module MetaBuilder module Dsl module Main attr_accessor :metadata def install(name, &block) @metadata = Horn::Core::Dsl::BuildMetaData.new yield self if block_given? end def description(desc) @metadata.Description = desc end def get_metadata @metadata end end end end include MetaBuilder::Dsl::Main I somehow want to be able to get the @metadata property from the Clr code after an instance of the Dsl has ran. An instance of the Dsl looks like this currently: install :horn do description "A .NET build and dependency manager" end My C# code looks like this currently: var engine = Ruby.CreateEngine(); engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); engine.ExecuteFile(buildFile); var klass = engine.Runtime.Globals.GetVariable("get_metadata"); Is there anyway I can get at the @metadata property without having to pollute the Dsl instance? For that matter is my approach reasonable or is there perhaps a better way? Thanks in advance Paul -- Posted via http://www.ruby-forum.com/.
Hi, For anyone who is interested, I managed to solve this by creating a singleton to house an instance of the BuildMetaData class. My Ruby code ended up looking like this: module MetaBuilder module Dsl module Main def install(name, &block) yield self if block_given? end def get_from(name, url) puts name puts url end def description(desc) meta.metadata.Description = desc end class MetaDataAccessor attr_accessor :metadata private def initialize @metadata = Horn::Core::Dsl::BuildMetaData.new end public def self.instance @@instance ||= new end def self.get_metadata @metadata end end end end end def meta MetaBuilder::Dsl::Main::MetaDataAccessor.instance end class ClrAccessor def get_build_metadata meta.metadata end end include MetaBuilder::Dsl::Main I created the MetaDataAccessor to keep a singleton BuildMetaData instance. I could not work out the C# code to access a fully qualified class that is nested in between modules so I created the ClrAccessor class to provide access from the Clr. My C# code ended up looking like this: var engine = Ruby.CreateEngine(); engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); engine.ExecuteFile(buildFile); var klass = engine.Runtime.Globals.GetVariable("ClrAccessor"); var instance = engine.Operations.CreateInstance(klass); buildMetaData = (BuildMetaData)engine.Operations.InvokeMember(instance, "get_build_metadata"); I am fairly sure there is an easier way but for me it is progress. Any input into this "round the houses" approach would be appreciated. Cheers Paul Paul Cowan wrote:> Hi, > > I am trying to create a Dsl which will have instances that live in > individual Dsl .rb files and then run them from the CLR. > > I want to create and set the values of the Clr object in IronRuby and > then somehow have access to the CLR object after the .rb Dsl instance > file has run. > > Here is my Clr object which is very simple at the moment: > > namespace Horn.Core.Dsl > { > public class BuildMetaData : IBuildMetaData > { > public string Description { get; set; } > } > } > > I have the following module which I am using to specify my Dsl and which > will create an instance of the BuildMetaData specified above: > > module MetaBuilder > module Dsl > module Main > attr_accessor :metadata > def install(name, &block) > @metadata = Horn::Core::Dsl::BuildMetaData.new > yield self if block_given? > end > > def description(desc) > @metadata.Description = desc > end > > def get_metadata > @metadata > end > > end > end > end > > include MetaBuilder::Dsl::Main > > I somehow want to be able to get the @metadata property from the Clr > code after an instance of the Dsl has ran. > > An instance of the Dsl looks like this currently: > > install :horn do > description "A .NET build and dependency manager" > end > > My C# code looks like this currently: > > var engine = Ruby.CreateEngine(); > engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); > engine.ExecuteFile(buildFile); > var klass = engine.Runtime.Globals.GetVariable("get_metadata"); > > Is there anyway I can get at the @metadata property without having to > pollute the Dsl instance? > > For that matter is my approach reasonable or is there perhaps a better > way? > > Thanks in advance > > Paul-- Posted via http://www.ruby-forum.com/.
Tomas Matousek
2009-Mar-17 16:46 UTC
[Ironruby-core] Accessing the return value from a Dsl
What scope you would like the instance of BuildMetaData to appear in? There are basically 2 possibilities: 1) global Any global Ruby constants will appear in Runtime.Globals dictionary. So you can just assign the instance into a constant: MyInstance = Horn::Core::Dsl::BuildMetaData.new and get it back in C# via Globals.GetVariable("MyInstance") 2) in a DLR execution scope This is a little bit more tricky since Ruby doesn''t have a concept of execution scopes (unlike Python that has modules). IronRuby has a hook in method definition that publishes a method defined on a "main" object into the DLR scope. The "main" object is a singleton of Object class that Ruby creates for top-level scope self:> ruby -e ''p self''main In IronRuby you can do this: foo.rb: def self.my_method 123 end C#: var scope = engine.ExecuteFile("foo.rb"); var my_method = scope.GetVariable<Func<int>>("my_method") Console.WriteLine(my_method()); I''m still looking for improvements to DLR scope interop, so this might actually change in future. Tomas -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Paul Cowan Sent: Monday, March 16, 2009 4:40 PM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] Accessing the return value from a Dsl Hi, For anyone who is interested, I managed to solve this by creating a singleton to house an instance of the BuildMetaData class. My Ruby code ended up looking like this: module MetaBuilder module Dsl module Main def install(name, &block) yield self if block_given? end def get_from(name, url) puts name puts url end def description(desc) meta.metadata.Description = desc end class MetaDataAccessor attr_accessor :metadata private def initialize @metadata = Horn::Core::Dsl::BuildMetaData.new end public def self.instance @@instance ||= new end def self.get_metadata @metadata end end end end end def meta MetaBuilder::Dsl::Main::MetaDataAccessor.instance end class ClrAccessor def get_build_metadata meta.metadata end end include MetaBuilder::Dsl::Main I created the MetaDataAccessor to keep a singleton BuildMetaData instance. I could not work out the C# code to access a fully qualified class that is nested in between modules so I created the ClrAccessor class to provide access from the Clr. My C# code ended up looking like this: var engine = Ruby.CreateEngine(); engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); engine.ExecuteFile(buildFile); var klass = engine.Runtime.Globals.GetVariable("ClrAccessor"); var instance = engine.Operations.CreateInstance(klass); buildMetaData = (BuildMetaData)engine.Operations.InvokeMember(instance, "get_build_metadata"); I am fairly sure there is an easier way but for me it is progress. Any input into this "round the houses" approach would be appreciated. Cheers Paul Paul Cowan wrote:> Hi, > > I am trying to create a Dsl which will have instances that live in > individual Dsl .rb files and then run them from the CLR. > > I want to create and set the values of the Clr object in IronRuby and > then somehow have access to the CLR object after the .rb Dsl instance > file has run. > > Here is my Clr object which is very simple at the moment: > > namespace Horn.Core.Dsl > { > public class BuildMetaData : IBuildMetaData > { > public string Description { get; set; } > } > } > > I have the following module which I am using to specify my Dsl and which > will create an instance of the BuildMetaData specified above: > > module MetaBuilder > module Dsl > module Main > attr_accessor :metadata > def install(name, &block) > @metadata = Horn::Core::Dsl::BuildMetaData.new > yield self if block_given? > end > > def description(desc) > @metadata.Description = desc > end > > def get_metadata > @metadata > end > > end > end > end > > include MetaBuilder::Dsl::Main > > I somehow want to be able to get the @metadata property from the Clr > code after an instance of the Dsl has ran. > > An instance of the Dsl looks like this currently: > > install :horn do > description "A .NET build and dependency manager" > end > > My C# code looks like this currently: > > var engine = Ruby.CreateEngine(); > engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); > engine.ExecuteFile(buildFile); > var klass = engine.Runtime.Globals.GetVariable("get_metadata"); > > Is there anyway I can get at the @metadata property without having to > pollute the Dsl instance? > > For that matter is my approach reasonable or is there perhaps a better > way? > > Thanks in advance > > Paul-- Posted via http://www.ruby-forum.com/. _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core