Problems with including an interface in IronRuby
-
30-04-2021 - |
Question
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?
Solution
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 );
OTHER TIPS
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());
}
}