[Ironruby-core] Accessing the return value from a Dsl

Tomas Matousek Tomas.Matousek at microsoft.com
Tue Mar 17 12:46:35 EDT 2009


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



More information about the Ironruby-core mailing list