2016-05-04 10 views
0

Dieser Code funktioniertBetrieb könnte die Laufzeitfehler, wenn invoke ToString von int mit Emit

var toString = typeof(string).GetMethod("ToString", new Type[] { }); 

var dm = new DynamicMethod("MyToString", typeof(string), new Type[] { typeof(string) }); 

var il = dm.GetILGenerator(); 

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Callvirt, toString); 
il.Emit(OpCodes.Ret); 

Delegate d = dm.CreateDelegate(typeof(Func<string, string>)); 

var r = d.DynamicInvoke("10"); 

destabilisieren Dieser Code eine Ausnahme auslöst (System.Security.VerificationException. Der Betrieb der Laufzeit destabilisieren könnte)

var toString = typeof(int).GetMethod("ToString", new Type[] { }); 

var dm = new DynamicMethod("MyToString", typeof(string), new Type[] { typeof(int) }); 

var il = dm.GetILGenerator(); 

il.Emit(OpCodes.Ldarg_0); 
il.Emit(OpCodes.Callvirt, toString); 
il.Emit(OpCodes.Ret); 

Delegate d = dm.CreateDelegate(typeof(Func<int, string>)); 

var r = d.DynamicInvoke(10); 

warum?

Antwort

8

Mit Ldarg_0, können Sie den Wert des Arguments laden 0. Instanzmethoden auf einem Werttyp T Für den Aufruf, die impliziten this Parameter nicht Typen haben T, es gibt ref T hat, so dass Sie nicht den Wert laden müssen, aber ein Verweis auf Argument 0. Die Ldarga Anweisung wird das für Sie tun. Das ist das unmittelbare Problem.

Ein weniger schwerwiegendes Problem, obwohl eines, das für mich unentdeckt bleibt und ich bin nicht 100% sicher, wenn es unbedingt erforderlich ist, dass Sie die Call Anweisung für Instanzmethoden für Werttypen oder in bestimmten Fällen sein sollten, das Constrained Präfix vor der Callvirt Anweisung.

Im Allgemeinen raten Sie nicht, welche CIL-Anweisungen Sie benötigen. Schreiben Sie Ihren beabsichtigten Code einmal in C#, kompilieren Sie ihn und disassemblieren Sie das Ergebnis. Das sagt Ihnen die genauen Anweisungen, die Sie leicht arbeiten sehen können.

+0

Der Ldarga-Befehl funktioniert auch nicht, ich werde versuchen, zu dekompilieren, um zu sehen, wie es funktioniert –

+0

'Ldarga' +' Call' ist was Roslyn auch erzeugt. Wenn das bei dir nicht funktioniert, dann machst du etwas falsch, aber ich weiß nicht was. Für eine schnelle Online-Dekompilierungsprüfung versuchen Sie 'öffentliche statische Klasse C {öffentliche statische Zeichenkette F (int i) => i.ToString(); } auf http://tryroslyn.azurewebsites.net/. – hvd

+0

Es tut mir leid, ich habe es wieder mit der Ldarga versucht und funktioniert jetzt, ich weiß nicht, was ich gestern falsch gemacht habe –