Проблемы с включением интерфейса в IronRuby - PullRequest
1 голос
/ 03 января 2012

У меня есть интерфейс, который выглядит примерно так:

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. Я делаю это неправильно или я не могу делать то, что пытаюсь сделать?

Ответы [ 2 ]

4 голосов
/ 17 февраля 2012

То, что вы хотите сделать, возможно; IronRuby поддерживает реализацию интерфейсов, смешивая интерфейс в классе.

При выполнении вашего примера я получаю следующее исключение:

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

Это не означает, что объект не может быть приведен к IMyInterface, это просто означает, что движок Ruby не знает, что такое IMyInterface. Это потому, что вы должны указать IronRuby, в каких сборках искать IMyInterface, используя ScriptRuntime.LoadAssembly. Например, чтобы загрузить текущую сборку, вы можете сделать это:

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

Ниже показано, что вы можете вызывать метод, определенный в Ruby, из C #, вызывая методы на интерфейсе:

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());
  }
}
1 голос
/ 18 января 2012

Невозможно реализовать интерфейс CLR в IronRuby и передать его обратно в CLR.MyInterfaceImpl в вашем примере - это класс Ruby, а не CLR-реализация IMyInterface.

Я исправлен, согласно сообщению Джимми Шементи.

Однако вы можете использовать типы IronRuby.как динамические объекты внутри вашего кода .NET:


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

...