2014-01-10 122 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);