2010-02-19 43 views
2

我使用IronRuby和試圖想出一個無縫傳遞給C#塊。這個問題是從How to use an IronRuby block in C#開始的,它指示塊不能在IronRuby和C#之間傳遞。使用的IronRuby的包裝方法得到一個塊到C#

我的後續問題是是否有到acheive使用Ruby的包裝方法,使塊爲lambda或PROC對象,並把它傳遞給C#同一個目標的方法嗎?

一些代碼,沿着想什麼,我能夠做的線條低於。該代碼不起作用,但希望其意圖足夠清晰。

string scriptText = 
    @"def BlockTest 
    result = csharp.BlockTest somehow-pass-the-block ("hello") 
    puts result 
    end 
    BlockTest { |arg| arg + 'world'}"; 

Console.WriteLine("Compiling IronRuby script."); 
ScriptEngine scriptEngine = Ruby.CreateEngine(); 
ScriptScope scriptScope = scriptEngine.CreateScope(); 
scriptScope.SetVariable("csharp", new BlockTestClass()); 
scriptEngine.Execute(scriptText, scriptScope); 

的C#BlockTest類是:

public class BlockTestClass 
{ 
    public void BlockTest(Func<string, string> block) 
    { 
     Console.WriteLine(block("hello ")); 
    } 
} 

回答

2

塊是一個神祕的東西,並不存在於CLR中。然而,Ruby有一個類似於CLR代表的proc

例如,這應該很好地工作:

C#:

public class SomeClass { 
    public static void Run(Func<int, int> func) { ... } 
} 

紅寶石:

proc = lambda { |i| i + 10 } 
SomeClass.Run(proc) 

有幾種方法來創建新的特效(很多人喜歡Proc.new,但它並不像C#函數那樣工作,所以我更喜歡lambda),但關鍵點是:

lambda(和Proc.new)是一個函數 - 傳遞的功能的塊,並且它會產生一個新的對象Proc它包裝塊。

還有的隱含轉換塊時,它們傳遞給函數,使用&以特效的方式。

紅寶石:

def each 
    yield 1 
end 

相同

def each(&block) 
    block.call 1 
end 

&需要已傳遞給方法(其否則將被隱含地通過yield調用)的塊,並將其轉換變成Proc。一旦它是一個proc,你可以傳遞它,把它放在數組中,或者傳遞給C#。

於是,打電話給你的C#方法,你有兩個選擇:

  1. 創建包裝方法這需要的塊,並使用&將其轉換爲一個PROC。然後你可以用這個過程調用底層的C#方法

  2. 在ruby中使用lambdaProc.new直接創建一個proc,並將它傳遞給C#方法。

實例:

C#代碼(公共):

public static class MyClass 
{ 
    public static void Print(Func<int, int> converter) 
    { 
     Console.WriteLine("1: {0}", converter(1)); 
    } 
} 

紅寶石代碼1(包裝):

class MyClass 
    class << self # this is only needed to alias class (static) methods, not for instance methods 
    alias_method :original_print, :print 
    end 

    def self.print(&block) 
    original_print block 
    end 
end 

MyClass.print {|i| i * 10} 

紅寶石代碼2(直接):

MyClass.print lambda{|i| i * 10} 
+0

很棒,thx! – sipwiz 2010-02-28 23:21:37

0

我不知道完整的答案,但你可能會得到更遠如果你打電話block.to_proc把它轉換成一個可調用的進程內對象。

0

我曾與Func<> -Delegates和塊或特效沒有成功。懶洋洋地,我在C#中使用了Proc-Class,並且從Ruby中調用它block.to_proc。在C#中,您可以使用Proc.Call並投射您的結果。

它已經有一段時間了,所以也許這已經過時了。