从 C# 中实例化模块中的 ruby​​ 类

发布于 2024-10-19 07:58:25 字数 1202 浏览 8 评论 0原文

我正在尝试重用我不久前在 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# 中调用的单独的类,但如果我不必这样做,我宁愿不这样做。任何指导将不胜感激。

I'm attempting to re-use some ruby classes I wrote a while back within an ASP.NET MVC 2 project. The issue I'm having is if a class is within a Module I can't seem to instantiate it. If I move the class outside of the module it works fine. Here is a scaled down version of the class I want to instantiate:

module Generator
  class CmdLine
    attr_accessor :options

    def initialize(output)
    end

    def run(args=[])
    end
  end
end

If comment out the module portion I can create the object. Am I doing something wrong? Here is the C# code:

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

I have a work around - creating a separate class that I can call from within C# but if I don't have to do that I'd rather not do it. Any guidance would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

寻梦旅人 2024-10-26 07:58:25

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

将下一个代码添加到 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);

有点黑客,但是嘿,它作品! :)

I know this is kind of a hack/workaround, but I managed to do it this way:

Add the next code to the end of your ruby file:

def hack(s)
  eval(s)
end

Now your C# code would look like that:

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

Kind of a hack, but hey, it works! :)

我也只是我 2024-10-26 07:58:25

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

根本就不需要再喊了。您拥有可以从 C# 本地调用的东西。

I would create a new IronRuby project, take your original Ruby code and port/compile it into a .NET library.

No more need to call out at all. You have something that can be called natively from C#.

荒芜了季节 2024-10-26 07:58:25

@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

The solution @Shay Friedman proposed is unnecessary.

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());
}

output

Hello from cmdLine with the output []
Hello from cmdLine with the output InvokeMember
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文