从C#中实例化一个Module中的ruby类

时间:2011-02-24 15:33:48

标签: c# c#-4.0 ironruby

我正在尝试重用一些我在ASP.NET MVC 2项目中写过的ruby类。我遇到的问题是如果一个类在一个模块中我似乎无法实例化它。如果我将课程移到模块之外,它可以正常工作。这是我要实例化的类的缩小版本:

module Generator
  class CmdLine
    attr_accessor :options

    def initialize(output)
    end

    def run(args=[])
    end
  end
end

如果注释掉模块部分,我可以创建对象。难道我做错了什么?这是C#代码:

var engine  = Ruby.CreateEngine();
var searchPaths = engine.GetSearchPaths().ToList();
searchPaths.Add(@"c:\code\generator\lib");
searchPaths.Add(@"C:\Ruby-ri-192\lib\ruby\1.9.1");
engine.SetSearchPaths(searchPaths);

engine.ExecuteFile(@"c:\code\generator\lib\generator\generator_cmd_line.rb");
var rubyCmdLineObj = engine.Runtime.Globals.GetVariableNames();
// These lines works when I comment out the module
// var genCmdLineObj = engine.Runtime.Globals.GetVariable("CmdLine");
// var cmdLineObj = engine.Operations.CreateInstance(genCmdLineObj);
// var results = engine.Operations.InvokeMember(cmdLineObj, "run");
//  return Content(results);
var sb = new StringBuilder();
foreach (var name in rubyCmdLineObj)
{
  sb.AppendFormat("{0} ", name);
}

return Content(sb.ToString());

我有一个解决方法 - 创建一个单独的类,我可以在C#中调用,但如果我不必这样做,我宁愿不这样做。任何指导都将不胜感激。

3 个答案:

答案 0 :(得分:0)

我将创建一个新的IronRuby项目,获取原始的Ruby代码并将其编译或编译到.NET库中。

根本不需要打电话。你可以从C#本地调用一些东西。

答案 1 :(得分:0)

我知道这是一种黑客攻击/解决方法,但我设法这样做了:

将下一个代码添加到ruby文件的末尾:

def hack(s)
  eval(s)
end

现在你的C#代码看起来像那样:

var engine = Ruby.CreateEngine();

var scope = engine.ExecuteFile(@"c:\code\generator\lib\generator\generator_cmd_line.rb");

var genCmdLineObj = engine.Execute(String.Format("hack('{0}::{1}')", "Generator", "CmdLine"), scope);
var cmdLineObj = engine.Operations.CreateInstance(genCmdLineObj);
var results = engine.Operations.InvokeMember(cmdLineObj, "run");
return Content(results);

有点黑客,但嘿,它有效! :)

答案 2 :(得分:0)

@Shay Friedman提出的解决方案是不必要的。

<强> gen.rb

module Generator
  class CmdLine
    attr_accessor :options

    def initialize(output)
        @output = output
    end

    def run(args=[])
        puts "Hello from cmdLine with #{@output} #{args}"
    end
  end
end

<强> CSHARP

void Main()
{
    var engine = Ruby.CreateEngine();
    var buffer = new MemoryStream();
    engine.Runtime.IO.SetOutput(buffer, new StreamWriter(buffer));
    engine.ExecuteFile(@"c:\temp\gen.rb");
    ObjectHandle handle = engine.ExecuteAndWrap("Generator::CmdLine.new('the output')");
    var scope = engine.CreateScope();
    scope.SetVariable("myvar", handle);
    engine.Execute("myvar.run", scope);
    engine.Operations.InvokeMember(handle.Unwrap(), "run", "InvokeMember");
    buffer.Position = 0;
    Console.WriteLine(new StreamReader(buffer).ReadToEnd());
}

<强>输出

Hello from cmdLine with the output []
Hello from cmdLine with the output InvokeMember