2

我正在使用 IronRuby 并试图想出一个无缝将块传递给 C# 的方法。这个问题是如何在 C# 中使用 IronRuby 块的后续问题,这表明块不能在 IronRuby 和 C# 之间传递。

我接下来的问题是,是否有一种方法可以使用 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 "));
    }
}
4

3 回答 3

2

块是 CLR 中并不真正存在的神秘事物。然而,Ruby 确实有一个proc类似于 CLR 委托的。

例如,这应该可以正常工作:

C#:

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

红宝石:

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

有几种方法可以创建新的 procs(很多人更喜欢Proc.new,但它的工作方式与 C# 函数不太一样,所以我更喜欢 lambda),但关键是:

lambda(and Proc.new) 是一个函数 - 您将函数传递给一个块,它会生成一个Proc包装该块的新对象。

还有一种方法可以在将块传递给函数时将它们隐式转换为 proc,使用&.

红宝石:

def each
  yield 1
end

是相同的

def each(&block)
  block.call 1
end

&获取已传递给方法的块(否则将由 隐式调用)yield并将其转换为Proc. 一旦它是一个 proc,您可以将它传递给它,将它粘贴在数组中,或者将它传递给 C#。

因此,要调用 C# 方法,您有两种选择:

  1. 创建一个接受块的包装器方法,并用于&将其转换为过程。然后,您可以使用此 proc 调用底层 C# 方法

  2. 在ruby中使用lambdaorProc.new直接创建一个proc,并将其传递给C#方法。

例子:

C#代码(常用):

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

Ruby 代码 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}

Ruby 代码 2(直接):

MyClass.print lambda{|i| i * 10}
于 2010-02-28T19:36:15.850 回答
0

我不确定完整的答案,但是如果您调用block.to_proc将其转换为可调用的 Proc 对象,您可能会走得更远。

于 2010-02-19T00:31:14.393 回答
0

Func<>我在-Delegates 和 Blocks 或 Procs上没有成功。懒惰地,我Proc在 C# 中使用了 -Class 并从 Ruby 中调用它block.to_proc。在 C# 中,您可以使用Proc.Call并转换您的结果。

已经有一段时间了,所以也许这已经过时了。

于 2010-02-23T15:25:31.803 回答