[英]Instantiating a ruby class that is in a Module from within C#
我试图重用我在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#中调用的单独的类,但是如果不必这样做,我宁愿不这样做。 任何指导将不胜感激。
@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
尖锐的
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
我将创建一个新的IronRuby项目,将您原始的Ruby代码并将其移植/编译到.NET库中。
完全没有必要大声疾呼。 您可以从C#中本地调用某些东西。
我知道这是一种破解/解决方法,但是我设法做到了:
将下一个代码添加到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);
有点骇客,但嘿,行得通! :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.