Har du nogensinde set Java’s DynamicProxy, så må du være lidt midsundelig. Man forstår simpelthen ikke, hvorfor folkene bag .NET, ikke har stillet den feature til rådighed. Men hov – det har de! Godt nok ikke så fint indpakket, som i Java, men den er der via Reflection.Emit. En statisk metode, der lader dig tilføje IL til en assembly runtime. Ret mig hvis jeg har opfattet det forkert, men for mig ser det sådan ud.
Jeg havde lavet forsøg med CodeDom, men kan ikke lide det overhead der er med runtime kompilering af kildekode. Så Emit er blevet min nye ven. Jeg starter ud med en opgave der er meget simpel, men som ikke kan lade sig gøre i Java: Dynamisk delegate. Lad os sige vi har brug for at hooke dynamisk kode op på en klik event – for eksemplets skyld, skal min dynamiske kode blot skrive: Hello world, men det kunne være hvad som helst.
Man starter et proxy objekt: DynamicMethod, som man så kan føje IL til via en ILGenerator.
var method = new DynamicMethod("", null, null);
var il = method.GetILGenerator();
I eksemplet her, vil jeg blot lave en delegate, så derfor er det ikke nødvendigt at angive et navn til metoden, ligesom retur type og parametre angives til null. Med ILGenerator’en, kan man nu “Emitte” IL til metoden:
il.EmitWriteLine("Hello world");
// ldstr "HelloWorld"
// call void [mscorlib]System.Console::WriteLine(string)
il.Emit(OpCodes.Ret);
// ret
Nu har vi dannet vores IL dynamisk, og så er der ikke andet tilbage, end at hooke metoden op på en event:
var myEvent = (Action)method.CreateDelegate(typeof(Action));
// Og så rejser vi eventen:
myEvent();
Det her er virkelig en kraftfuld feature, og er endnu et værktøj i C# (og VB.NET) udviklerens værktøjskasse med dynamiske muligheder. Eneste ulempe, som jeg ser det, er at man ikke kan debugge i VS.NET, og at man skal til at lære IL.
Jeg vil spike lidt på C# 4.0, og se om der er kommet features, der kan lette ovenstående.
Code on…