1

我正在尝试创建一个 Dsl,该 Dsl 将具有位于单个 Dsl .rb 文件中的实例,然后从 CLR 运行它们。

我想在 IronRuby 中创建和设置 Clr 对象的值,然后在 .rb Dsl 实例文件运行后以某种方式访问​​ CLR 对象。

这是我的 Clr 对象,目前非常简单:

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

我有以下模块用于指定我的 Dsl 并将创建上面指定的 BuildMetaData 的实例:

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

在 Dsl 的实例运行后,我以某种方式希望能够从 Clr 代码中获取 @metadata 属性。

目前 Dsl 的一个实例如下所示:

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

我的 C# 代码目前如下所示:

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

无论如何我可以在不污染 Dsl 实例的情况下获得@metadata 属性吗?

4

1 回答 1

2

对于任何感兴趣的人,我设法通过创建一个单例来容纳 BuildMetaData 类的实例来解决这个问题。

我的 Ruby 代码最终看起来像这样:

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

我创建了 MetaDataAccessor 来保留一个单例 BuildMetaData 实例。

我无法计算出 C# 代码来访问嵌套在模块之间的完全限定类,因此我创建了 ClrAccessor 类来提供来自 Clr 的访问。

我的 C# 代码最终看起来像这样:

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

我相当肯定有一个更简单的方法,但对我来说这是进步。

对这种“围绕房屋”方法的任何投入将不胜感激。

于 2009-03-16T23:41:36.630 回答