2009-03-16 5 views
1

J'essaye de créer un Dsl qui aura des instances qui vivent dans fichiers Dsl .rb individuels, puis les exécuter à partir du CLR.Accéder à la valeur de retour à partir d'un Dsl IronRuby

Je veux créer et définir les valeurs de l'objet Clr dans IronRuby et alors en quelque sorte l'accès à l'objet CLR après l'instance .rb Dsl fichier a été exécuté.

Voici mon objet clr qui est très simple au moment:

namespace Horn.Core.Dsl 
{ 
    public class BuildMetaData : IBuildMetaData 
    { 
     public string Description { get; set; } 
    } 
} 

Je le module suivant que je me sers de préciser mon Dsl et qui va créer une instance de la BuildMetaData spécifiée ci-dessus:

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 

Je veux en quelque sorte d'être en mesure d'obtenir la propriété @metadata à partir du code Clr après une instance de la Dsl a couru.

Une instance de la Dsl ressemble à ce moment:

install :horn do 
    description "A .NET build and dependency manager" 
end 

Mon code C# ressemble à ce moment:

var engine = Ruby.CreateEngine(); 
engine.Runtime.LoadAssembly(typeof(BuildMetaData).Assembly); 
engine.ExecuteFile(buildFile); 
var klass = engine.Runtime.Globals.GetVariable("get_metadata"); 

Y at-il de toute façon je peux obtenir à la propriété @metadata sans avoir à polluer l'instance Dsl?

Répondre

2

Pour tous ceux qui sont intéressés, j'ai réussi à résoudre ce problème en créant un singleton pour héberger une instance de la classe BuildMetaData.

Code Mon Ruby a fini par ressembler à ceci:

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 

J'ai créé le MetaDataAccessor de garder un singleton BuildMetaData exemple.

Je ne pouvais pas élaborer le code C# pour accéder à une classe pleinement qualifiée qui est imbriquée entre les modules, donc j'ai créé la classe ClrAccessor à fournir un accès à partir du Clr.

Mon code C# a fini par ressembler à ceci:

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"); 

Je suis assez sûr qu'il ya un moyen plus facile pour moi, mais il est un progrès.

Toute contribution à cette approche «arrondir les maisons» serait appréciée.

Questions connexes