# Accessing the return value from a Dsl

**URL:** <https://www.ruby-forum.com/t/accessing-the-return-value-from-a-dsl/162975>\
**Category:** IronRuby\
**Created:** [March 16, 2009, 11:51am UTC](https://www.ruby-forum.com/t/accessing-the-return-value-from-a-dsl/162975 "2009-03-16T11:51:00Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![paul](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/bbe5ce/32.png) [@paul](https://www.ruby-forum.com/u/paul)\
**Post date:** [March 16, 2009, 11:51am UTC](https://www.ruby-forum.com/t/accessing-the-return-value-from-a-dsl/162975/1 "2009-03-16T11:51:00Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paul](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/bbe5ce/32.png) [@paul](https://www.ruby-forum.com/u/paul)\
**Post date:** [March 17, 2009, 12:40am UTC](https://www.ruby-forum.com/t/accessing-the-return-value-from-a-dsl/162975/2 "2009-03-17T00:40:20Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paul](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/bbe5ce/32.png) [@paul](https://www.ruby-forum.com/u/paul)\
**Post date:** [March 17, 2009, 6:40pm UTC](https://www.ruby-forum.com/t/accessing-the-return-value-from-a-dsl/162975/3 "2009-03-17T18:40:48Z")

</div>

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”)

1. 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\>(“my\_method”)  
Console.WriteLine(my\_method());

I’m still looking for improvements to DLR scope interop, so this might  
actually change in future.

Tomas
