Note that there are some explanatory texts on larger screens.

plurals
  1. POprevent DynamicMethod VerificationException - operation could destabilize the runtime
    primarykey
    data
    text
    <p>I am using IL generation to create a simple deserializer method which takes strings out of a Lucene document and sets properties or fields of a reference-type object (POCO).</p> <p>Whenever I try to run the generated method, I receive a VerificationException error. There are other questions regarding this error, a few of which have to do with DynamicMethods, but from what I can tell the issue I am having is different.</p> <p><a href="https://stackoverflow.com/questions/1277779/operation-could-destablize-the-runtime-and-dynamicmethod-with-value-types">operation-could-destablize-the-runtime-and-dynamicmethod-with-value-types</a></p> <p><a href="https://stackoverflow.com/questions/615530/msil-operation-could-destabilize-the-runtime-exception">msil-operation-could-destabilize-the-runtime-exception</a></p> <p>Although the method will get more complicated in the future, I have it just doing string assignment right now. The method I am trying to create dynamically will look exactly like this:</p> <pre><code>public static PocoObject ExampleMethod(Document document) { var poco = new PocoObject(); poco.ID = document.Get("ID"); poco.DisplayText = document.Get("DisplayText"); poco.PropId = document.Get("PropId"); return poco; } </code></pre> <p>Where PocoObject looks like this:</p> <pre><code>class PocoObject { public string ID; public string DisplayText; public string PropId { get; set; } } </code></pre> <p>I tried to replicate the IL generated from the compile-time code EXACTLY (even the unnecessary bits) and it looks like this:</p> <pre><code>.method public instance object 'Deserializebe6d500b-d35f-4f7a-a9b3-88f6bca5fb93'(class [Lucene.Net]Lucene.Net.Documents.Document A_1) cil managed { // Code size 65 (0x41) .maxstack 4 IL_0000: nop IL_0001: newobj instance void [LukeMapperTest]LukeMapperTest.PocoObject::.ctor() IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldarg.0 IL_0009: ldstr "ID" IL_000e: callvirt instance string [Lucene.Net]Lucene.Net.Documents.Document::Get(string) IL_0013: stfld string [LukeMapperTest]LukeMapperTest.PocoObject::ID IL_0018: ldloc.0 IL_0019: ldarg.0 IL_001a: ldstr "DisplayText" IL_001f: callvirt instance string [Lucene.Net]Lucene.Net.Documents.Document::Get(string) IL_0024: stfld string [LukeMapperTest]LukeMapperTest.PocoObject::DisplayText IL_0029: ldloc.0 IL_002a: ldarg.0 IL_002b: ldstr "PropId" IL_0030: callvirt instance string [Lucene.Net]Lucene.Net.Documents.Document::Get(string) IL_0035: callvirt instance void [LukeMapperTest]LukeMapperTest.PocoObject::set_PropId(string) IL_003a: nop IL_003b: ldloc.0 IL_003c: stloc.1 IL_003d: br.s IL_003f IL_003f: ldloc.1 IL_0040: ret } // end of method Test::'Deserializebe6d500b-d35f-4f7a-a9b3-88f6bca5fb93' </code></pre> <p>I have managed to save the DynamicMethod to an assembly on disk, inspected it, and this is exactly what it brings up. Line for line it is the same as the compile-time method IL.</p> <p>Nevertheless, when executing the dynamic method, the error above is thrown. Does anyone have any idea how I could fix this?</p> <p>Note: I have the source code on GitHub if anyone would like to take a closer look. The IL Generation code is in LukeMapper.cs:GetDumbDeserializer() (line 133)</p> <p><a href="https://github.com/lelandrichardson/LukeMapper" rel="nofollow noreferrer">LukeMapper GitHub repo</a></p> <p>All help is appreciated! Thanks!</p> <hr> <p>EDIT: So I have simplified the IL generation code and it is essentially the following:</p> <pre><code>private static Func&lt;Document, object&gt; GetDumbDeserializer(Type type) { var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(object), new[] { typeof(Document) }, true); var il = dm.GetILGenerator(); var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); il.Emit(OpCodes.Nop); il.DeclareLocal(type); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Stloc_0); Label returnLabel = il.DefineLabel(); //stack is [target] var getFieldValue = typeof(Document).GetMethod("Get", BindingFlags.Instance | BindingFlags.Public); foreach (var setter in settableProperties) { il.Emit(OpCodes.Ldloc_0);// [target] il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldstr, setter.Name); il.Emit(OpCodes.Callvirt, getFieldValue); il.Emit(OpCodes.Stfld, setter.Field); } il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Stloc_1); // stack is empty il.Emit(OpCodes.Br_S, returnLabel); il.MarkLabel(returnLabel); il.Emit(OpCodes.Ldloc_1); // stack is [rval] il.Emit(OpCodes.Ret); return (Func&lt;Document, object&gt;)dm.CreateDelegate(typeof(Func&lt;Document, object&gt;)); } </code></pre> <p>I added in the <code>il.DeclareLocal(type)</code> (where type is PocoObject) per kvbs's comment, but I'm not sure if I am putting it in the right place (or if it matters).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload