【问题标题】:Problems with including an interface in IronRuby在 IronRuby 中包含接口的问题
【发布时间】:2012-01-03 16:06:11
【问题描述】:

我有一个看起来像这样的界面:

interface IMyInterface {
    MyObject DoStuff(MyObject o);
}

我想在 IronRuby 中编写这个接口的实现,并将对象返回以供以后使用。

但是当我尝试做类似的事情时

var code = @"
    class MyInterfaceImpl
        include IMyInterface

        def DoStuff(o)
            # Do some stuff with o
            return o
        end
    end

    MyInterfaceImpl.new";

Ruby.CreateEngine().Execute<IMyInterface>(code);

我收到一个错误,因为它无法转换为 IMyInterface。是我做错了,还是不能做我想做的事?

【问题讨论】:

    标签: c# ironruby dynamic-language-runtime


    【解决方案1】:

    你想做的都是可能的; IronRuby 支持通过将接口混合到类中来实现接口。

    运行你的例子我得到了这个异常:

    Unhandled Exception: System.MemberAccessException: uninitialized constant MyInte
    rfaceImpl::IMyInterface
    

    这并不意味着对象不能转换为IMyInterface,它只是意味着Ruby 引擎不知道IMyInterface 是什么。这是因为您必须使用 ScriptRuntime.LoadAssembly 告诉 IronRuby 在哪些程序集中查找 IMyInterface。例如,要加载当前程序集,您可以这样做:

    ruby.Runtime.LoadAssembly(typeof(IMyInterface).Assembly);
    

    以下显示您可以通过调用接口上的方法从 C# 调用 Ruby 定义的方法:

    public class MyObject {
    }
    
    public interface IMyInterface {
        MyObject DoStuff(MyObject o);
    }
    
    public static class Program {
      public static void Main(string[] args) {
        var code = @"
        class MyInterfaceImpl
            include IMyInterface
    
            def DoStuff(o)
                # Do some stuff with o
                puts o
                return o
            end
        end
    
        MyInterfaceImpl.new";
    
        var ruby = IronRuby.Ruby.CreateEngine();
        ruby.Runtime.LoadAssembly(typeof(MyObject).Assembly);
        var obj = ruby.Execute<IMyInterface>(code);
        obj.DoStuff(new MyObject());
      }
    }
    

    【讨论】:

    • @Jimmy_Schementi 感谢您提供的信息!不过,当我尝试类似的事情时,我得到了一个不同的异常——我在一个单独的程序集中有一个接口“IDummy”,我尝试在 IronRuby 中“实现”它。我得到的例外是“无法将混凝土转换为 IIntf”。如果我在不强制转换的情况下从 IR 创建对象并检查其类型,则 IsAssignableFrom(typeof my interaface) 返回 false。我在做什么不同?
    • 看不到你在做什么,我只能猜测。
    【解决方案2】:

    不可能在 IronRuby 中实现 CLR 接口并将其传递回 CLR。您的示例中的“MyInterfaceImpl”是一个 Ruby 类,而不是“IMyInterface”的 CLR 实现。

    根据 Jimmy Schementi 的帖子,我的立场是正确的。

    但是,您可以在 .NET 代码中使用 IronRuby 类型作为动态对象:

    var engine = Ruby.CreateRuntime().GetEngine("rb"); engine.Execute("/*你的脚本在这里*/"); 动态 ruby​​Scope = engine.Runtime.Globals; 动态 myImplInstance = ruby​​Scope.MyInterfaceImpl.@new(); var input = //.. 你的参数 var myResult = myImplInstance.DoStuff(输入);

    【讨论】:

    • 这是完全错误的。支持在 IronRuby 中实现接口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 2021-12-30
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多