简体   繁体   中英

Using Reflection.Emit to implement generic interface

I'm using Reflection.Emit to define a new type, and I'd like the type to implement IComparable(T) , where T would be the newly defined type.

class DefinedType : IComparable<DefinedType>
{
//...
}

It seems to me like I have a chicken-and-egg problem.

As a fallback, I can always just implement IComparable , but if possible I'd like the generic interface; I just can't see how I can do it using Emit, because the type doesn't exist before I define it.

This should work:

var tb = mb.DefineType("Test", TypeAttributes.Public);
var iface = typeof(IComparable<>).MakeGenericType(tb);
tb.AddInterfaceImplementation(iface);

var meb = tb.DefineMethod("CompareTo", MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), new [] { tb } );
var il = meb.GetILGenerator();
il.ThrowException(typeof(Exception));

var type = tb.CreateType();

Fortunately, TypeBuilder inherits from Type, so you can use it in MakeGenericType .

As a verification, this works:

var o1 = Activator.CreateInstance(type);
var o2 = Activator.CreateInstance(type);

typeof(IComparable<>).MakeGenericType(o1.GetType()).GetMethod("CompareTo").Invoke(o1, new [] { o2 }).Dump();

You don't have to bind the generated method to the interface in any way, it's enough that their signature is the same. Doing explicit interface implementation might be a bit more tricky, but you shouldn't need that.

When calling MakeGenericType() to turn IComparable<> into IComparable<DefinedType> , you can just pass it your TypeBuilder . The code could look something like:

var boundComparerType = typeof(IComparable<>).MakeGenericType(typeBuilder);
typeBuilder.AddInterfaceImplementation(boundComparerType);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM