2010-02-19 6 views
2

으로 가져옵니다. IronRuby를 사용하고 있으며 C#으로 블록을 원활하게 전달하려고합니다. 이 질문은 How to use an IronRuby block in C#에서 IronRuby와 C# 사이에 블록을 전달할 수 없음을 나타냅니다.IronRuby 래퍼 메서드를 사용하여 블록을 C#

내 후속 질문은 블록을 람다 또는 Proc 개체로 만들고이를 C#으로 전달하기 위해 Ruby 래퍼 메서드를 사용하여 동일한 목표를 달성 할 수있는 방법이 있는지 여부입니다.

내가 할 수있는 일에 따르는 코드 중 일부는 다음과 같습니다. 코드가 작동하지 않지만 희망 사항이 충분히 명확하다.

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 (및 Proc.new)은 함수입니다. 블록에 함수를 전달하면 블록을 래핑하는 새 Proc 객체가 생성됩니다.

&을 사용하여 블록을 함수에 전달할 때 암시 적으로 블록을 procs로 변환하는 방법이 있습니다.

루비 :

def each 
    yield 1 
end 

def each(&block) 
    block.call 1 
end 

& 동일하다 (달리 내재적 yield 호출 됐을) 메소드에 전달 된 블럭을 취하여 변환 Proc으로 일단 proc이면 proc을 전달하거나, 배열에 집어 넣거나, C#으로 전달할 수 있습니다.

  1. 이 블록을 소요하고, PROC로 변환 &를 사용하는 래퍼 방법을 만들기 :

    그래서, 당신의 C# 메서드를 호출, 두 가지 옵션이 있습니다. 그런 다음이 proc을 사용하여 기본 C# 메서드를 호출 할 수 있습니다.

  2. ruby에서 또는 Proc.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

원더풀! – sipwiz

0

나는 완전한 답변의 모르겠지만, 당신이 호출 된 Proc 객체로 변환 block.to_proc를 호출하는 경우 당신은 아마 더 얻을 것이다 :

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 클래스입니다.

0

나는 Func<> -Delegates and Blocks 또는 Procs와는 성공하지 못했습니다. 느슨하게, 나는 C#에서 Proc -Class를 사용하고 block.to_proc으로 Ruby에서 호출했다. C#에서는 Proc.Call을 사용하고 결과를 캐스팅 할 수 있습니다.

오래되었습니다. 어쩌면 구식 일 수 있습니다.