Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Or better yet, use Mono.Cecil. </p> <p>It will allow you to get at the individual instructions, even manipulating them and disassembling them (with the <a href="http://evain.net/blog/articles/2008/12/15/cecil-decompiler" rel="nofollow">mono decompiler addition</a>). </p> <p>Note that the decompiler is a work in progress (last time I checked it did not fully support lambda expressions and Visual Basic exception blocks), but you can have pretty decompiled output in C# pretty easily as far as you don't hit these boundary conditions. Also, work has progressed since.</p> <p>Mono Cecil in general let's you write the IL to a new assembly, as well, which you can then subsequently load into your appdomain if you like to play with bleeding edge.</p> <p><strong>Update</strong> I came round to trying this. Unfortunately I think I found what problem you run into. It turns out there is seems to be no way to get at the IL bytes for a generated type <em>unless</em> the assembly happened to get written out somewhere you can load it from.</p> <p>I assumed you could just get the bits via reflection (since the classes support the required methods), however the related methods just raise an exception <code>The invoked member is not supported in a dynamic module.</code> on invocation. You can try this with the code below, but <strong>in short I suppose it means that it ain't gonna happen</strong> unless you want to <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getfunctionpointerfordelegate.aspx" rel="nofollow">f*ck with <code>Marshal::GetFunctionPointerForDelegate()</code></a>. You'd have to binary dump the instructions and manually disassemble them as IL opcodes. There be dragons.</p> <p>Code snippet:</p> <pre><code>using System; using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; using System.Reflection.Emit; using System.Reflection; namespace REFLECT { class Program { private static Type EmitType() { var dyn = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Emitted"), AssemblyBuilderAccess.RunAndSave); var mod = dyn.DefineDynamicModule("Emitted", "Emitted.dll"); var typ = mod.DefineType("EmittedNS.EmittedType", System.Reflection.TypeAttributes.Public); var mth = typ.DefineMethod("SuperSecretEncryption", System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static, typeof(String), new [] {typeof(String)}); var il = mth.GetILGenerator(); il.EmitWriteLine("Emit was here"); il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); il.Emit(System.Reflection.Emit.OpCodes.Ret); var result = typ.CreateType(); dyn.Save("Emitted.dll"); return result; } private static Type TestEmit() { var result = EmitType(); var instance = Activator.CreateInstance(result); var encrypted = instance.GetType().GetMethod("SuperSecretEncryption").Invoke(null, new [] { "Hello world" }); Console.WriteLine(encrypted); // This works happily, print "Emit was here" first return result; } public static void Main (string[] args) { Type emitted = TestEmit(); // CRASH HERE: even if the assembly was actually for SaveAndRun _and_ it // has actually been saved, there seems to be no way to get at the image // directly: var ass = AssemblyFactory.GetAssembly(emitted.Assembly.GetFiles(false)[0]); // the rest was intended as mockup on how to isolate the interesting bits // but I didn't get much chance to test that :) var types = ass.Modules.Cast&lt;ModuleDefinition&gt;().SelectMany(m =&gt; m.Types.Cast&lt;TypeDefinition&gt;()).ToList(); var typ = types.FirstOrDefault(t =&gt; t.Name == emitted.Name); var operands = typ.Methods.Cast&lt;MethodDefinition&gt;() .SelectMany(m =&gt; m.Body.Instructions.Cast&lt;Instruction&gt;()) .Select(i =&gt; i.Operand); var requiredTypes = operands.OfType&lt;TypeReference&gt;() .Concat(operands.OfType&lt;MethodReference&gt;().Select(mr =&gt; mr.DeclaringType)) .Select(tr =&gt; tr.Resolve()).OfType&lt;TypeDefinition&gt;() .Distinct(); var requiredAssemblies = requiredTypes .Select(tr =&gt; tr.Module).OfType&lt;ModuleDefinition&gt;() .Select(md =&gt; md.Assembly.Name as AssemblyNameReference); foreach (var t in types.Except(requiredTypes)) ass.MainModule.Types.Remove(t); foreach (var unused in ass.MainModule .AssemblyReferences.Cast&lt;AssemblyNameReference&gt;().ToList() .Except(requiredAssemblies)) ass.MainModule.AssemblyReferences.Remove(unused); AssemblyFactory.SaveAssembly(ass, "/tmp/TestCecil.dll"); } } } </code></pre>
 

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