2014-01-10 5 views
5

Ich verwende Reflection.Emit, um einen neuen Typ zu definieren, und ich möchte, dass der Typ IComparable(T) implementiert, wobei T der neu definierte Typ wäre.Verwenden von Reflection.Emit, um generische Schnittstelle zu implementieren

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

Es scheint mir, als hätte ich ein Huhn-und-Ei-Problem.

Als Fallback kann ich immer nur IComparable implementieren, aber wenn möglich, würde ich gerne die generische Schnittstelle; Ich kann einfach nicht sehen, wie ich Emit verwenden kann, weil der Typ nicht existiert, bevor ich ihn definiere.

+0

Ich wünschte, ich hätte Zeit mit diesem .. aber ich freue mich auf jemand anderes zu antworten! –

+0

Ich sehe eine Methode ['addInterfaceImplementation'] (http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.addinterfaceimplementation (v = vs.110) .aspx), die Sie aufrufen können auf Ihrem ['TypeBuilder'] (http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder (v = vs.110) .aspx), nachdem Sie einen neuen Typ erstellt haben. Wären Sie nicht in der Lage, das "Comparable " hinterher mit diesem Verfahren zu Ihrem Typ hinzuzufügen? –

+0

@JeroenVannevel Ich glaube nicht, dass das erlaubt ist. Ich bin mir ziemlich sicher, dass Sie 'CreateType' nur einmal aufrufen können. – Anthony

Antwort

3

Diese Arbeit sollte:

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

Glücklicherweise Typebuilder von Typ erbt, so können Sie es in MakeGenericType verwenden.

Als Verifikation, das funktioniert:

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

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

Sie müssen nicht die generierte Methode zur Schnittstelle in irgendeiner Weise binden, es ist genug, dass ihre Unterschrift gleich ist. Die Implementierung einer expliziten Schnittstelle könnte etwas komplizierter sein, aber Sie sollten das nicht benötigen.

+0

Oh, ich sehe svick's Antwort suggeriert das schon. Nun, hier ist ein funktionierendes Sample, also nehmt einfach die Antwort von svick oder meins an, wie ihr wollt :) – Luaan

2

Wenn Sie MakeGenericType() anrufen, um IComparable<> in IComparable<DefinedType> zu verwandeln, können Sie einfach Ihre TypeBuilder übergeben. Der Code könnte etwa so aussehen:

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