在 IronRuby 中包含接口时出现的问题

发布于 2024-12-23 17:27:24 字数 510 浏览 1 评论 0原文

我有一个看起来像这样的接口:

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。我做错了吗,或者我不可能做我想做的事?

I have an interface which looks something like:

interface IMyInterface {
    MyObject DoStuff(MyObject o);
}

I want to write the implementation of this interface in IronRuby, and return the object for later use.

But when I try to do something like

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

I get an error because it can't be cast to IMyInterface. Am I doing it wrong, or isn't it possible to do what I'm trying to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

り繁华旳梦境 2024-12-30 17:27:24

你想做的事情是可能的; 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());
  }
}

What you want to do is possible; IronRuby supports implementing interfaces by mixing the interface into the class.

Running your example I get this exception:

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

This does not mean the object cannot be cast to an IMyInterface, it just means the Ruby engine doesn't know what IMyInterface is. This is because you must tell IronRuby what assemblies to look up IMyInterface in, using ScriptRuntime.LoadAssembly. For example, to load the current assembly, you can do this:

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

The following shows you can invoke a Ruby-defined method from C# by invoking methods on an interface:

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

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

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

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

    var engine = Ruby.CreateRuntime().GetEngine("rb");
    engine.Execute("/*your script goes here*/");

    dynamic rubyScope = engine.Runtime.Globals;
    dynamic myImplInstance = rubyScope.MyInterfaceImpl.@new();

    var input = //.. your parameter
    var myResult = myImplInstance.DoStuff(input );

It isn't possible to implement a CLR interface in IronRuby and pass it back into CLR. 'MyInterfaceImpl' in your example is a Ruby class, not a CLR realization of 'IMyInterface'.

I stand corrected, per Jimmy Schementi's post.

You could however use IronRuby types as dynamic objects inside your .NET code:

    var engine = Ruby.CreateRuntime().GetEngine("rb");
    engine.Execute("/*your script goes here*/");

    dynamic rubyScope = engine.Runtime.Globals;
    dynamic myImplInstance = rubyScope.MyInterfaceImpl.@new();

    var input = //.. your parameter
    var myResult = myImplInstance.DoStuff(input );

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文