使用Reflection.Emit实现通用接口

时间:2014-01-10 03:01:44

标签: c# generics reflection.emit

我使用Reflection.Emit来定义新类型,我希望实现IComparable(T)的类型,其中T将是新定义的类型。

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

在我看来,我有鸡和蛋的问题。

作为后备,我总是可以实现IComparable,但如果可能的话,我喜欢通用接口;我只是不知道如何使用Emit来做到这一点,因为在我定义它之前类型并不存在。

2 个答案:

答案 0 :(得分:3)

这应该有效:

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

幸运的是,TypeBuilder继承自Type,因此您可以在MakeGenericType中使用它。

作为验证,这有效:

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

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

您不必以任何方式将生成的方法绑定到接口,它们的签名就足够了。做显式接口实现可能会有点棘手,但你不应该那样。

答案 1 :(得分:2)

在致电MakeGenericType()以将IComparable<>变为IComparable<DefinedType>时,您可以将其传递给TypeBuilder。代码看起来像:

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