Over lunch today I hacked out a quick first pass at defining a dynamic type that understands how to implement the IDisposable interface. In a nutshell, RubyCLR will define an “anonymous type” in a dynamic assembly that maps to its corresponding Ruby class object. I’ll generate this dynamic type on the fly and marshal Ruby objects to the CLR as instances of that type (this is a gross simplification, but bear with me). This way Ruby objects can implement arbitrary CLR interfaces, and I can also provide mixin implementations for common ones like IDisposable or IBindingList.
Here’s the quick and dirty C# implementation that demonstrates how to make this happen:
static Type CreateBindableObject() {
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName assemblyName
= new AssemblyName("AnonymousRubyInteropAssembly");
AssemblyBuilder assemblyBuilder
= currentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder
= assemblyBuilder.DefineDynamicModule("AnonymousRubyInteropModule");
TypeBuilder typeBuilder
= moduleBuilder.DefineType("AnonymousInteropShim",
TypeAttributes.Public);
typeBuilder.AddInterfaceImplementation(typeof(IDisposable));
MethodBuilder methodBuilder
= typeBuilder.DefineMethod("Dispose",
MethodAttributes.Public
| MethodAttributes.Virtual,
typeof(void),
new Type[] { });
ILGenerator g = methodBuilder.GetILGenerator();
Type consoleType = typeof(Console);
MethodInfo mi = typeof(Console).GetMethod("WriteLine",
new Type[] { typeof(string) });
g.Emit(OpCodes.Ldstr, "Disposed!");
g.Emit(OpCodes.Call, mi);
g.Emit(OpCodes.Ret);
return typeBuilder.CreateType();
}
static void Main(string[] args) {
Type t = CreateBindableObject();
using (IDisposable obj = (IDisposable)Activator.CreateInstance(t)) {
Console.WriteLine("using object");
}
}
I would imagine that RubyCLR will eventually support a syntax that looks like:
class DisposableRubyObject
implements IDisposable
def dispose
Console.write_line 'disposed!'
end
end
where the implements method is some syntactical sugar around include.
This should make it much easier for me to support data binding scenarios. The current databinding stuff is all hard-coded, and this technique is far more flexible.
Recent Comments