2014-01-10 77 views
5

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

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

在我看来,我似乎有鸡与鸡蛋的问题。

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

+0

希望我有时间玩这个..但我期待着别人回答! –

+0

我看到一个方法['addInterfaceImplementation'](http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.typebuilder.addinterfaceimplementation(v = vs.110).aspx),你可以调用在您构建新类型之后,您的['TypeBuilder'](http://msdn.microsoft.com/zh-CN/library/system.reflection.emit.typebuilder(v = vs.110).aspx)。之后你不能使用这种方法将“Comparable ''添加到你的类型中吗? –

+0

@JeroenVannevel我不认为这是允许的。我很肯定你只能调用一次'CreateType'。 – Anthony

回答

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类型继承,所以你可以在MakeGenericType使用它。

作为验证,这个工程:

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

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

您不必生成的方法绑定到任何方式的界面,这是不够的,他们的签名是一样的。做明确的接口实现可能有点棘手,但你不应该需要这样做。

+0

哦,我看到svick的答案已经表明了这一点。那么,这里有一个完整的工作示例,所以请随时接受svick的回答或我的愿望:) – Luaan

2

当致电MakeGenericType()IComparable<>转换为IComparable<DefinedType>时,您可以将其传递给您的TypeBuilder。该代码可能看起来是这样的:

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