2011-02-24 30 views
0

我試圖重新使用一些我在ASP.NET MVC 2項目中編寫的ruby類。我遇到的問題是如果一個類在模塊內,我似乎無法實例化它。如果我將模塊移動到模塊外面,它可以正常工作。這裏是我想實例化的類的縮小版本:實例化C中的模塊中的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#中調用,但如果我沒有這樣做,我寧願不做。任何指導將不勝感激。

回答

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

一種黑客,但嘿,它的作品! :)

+0

謝謝謝伊!這有點黑客,但它的作品。感謝您花時間回答! – Rob 2011-02-27 16:54:25

0

我會創建一個新的IronRuby項目,將原始的Ruby代碼和端口/編譯到.NET庫中。

不需要再打電話了。你有一些可以從C#本地調用的東西。

+0

我想重新使用我已經有了。如果我必須重寫/端口,我會找到另一種方法來獲得我所需要的。我可能是錯的,但我不相信你可以將IronRuby項目編譯成DLL。我錯了嗎? – Rob 2011-02-24 16:05:55

+0

@Rob - 不,你不能直接將IronRuby編譯成DLL本身。但是,您可以將其託管在C#DLL中並將調用包裝到DLR中。根據Ruby代碼,你不應該有太多的改變,如果有的話。 – 2011-02-24 16:16:04

+0

酷我會檢查出來。謝謝Justin。 – Rob 2011-02-24 16:17:20

0

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

gen.rb

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