views:

49

answers:

2

I am writing a special-purpose mini-compiler and I often view disassembled CIL to figure out how to do things. But it's often not obvious how to translate the disassembled code to Reflection.Emit calls. Does a reference manual exist or any other source of information for doing this translation?

Edit: yes, mapping the opcodes to ILGenerator is pretty straightforward; I'm talking about all the other stuff like the .directives and attributes. For instance, how do you find out how to write the Reflection.Emit equivalent of something like Dictionary<TKey,TValue>?

.class public auto ansi serializable beforefieldinit Dictionary<TKey, TValue>
    extends System.Object
    implements System.Collections.Generic.IDictionary`2<!TKey, !TValue>,
    System.Collections.Generic.ICollection`1<valuetype 
        System.Collections.Generic.KeyValuePair`2<!TKey, !TValue>>, 
    ...
{
    .custom instance void System.Diagnostics.DebuggerDisplayAttribute::
        .ctor(string) = { string('Count = {Count}') }

    .method public hidebysig newslot virtual final instance bool TryGetValue
        (!TKey key, [out] !TValue& 'value') cil managed
    {
        .maxstack 3
        .locals init ([0] int32 num)
        ...

Or how about the "param" directive?

// public static void SayHello(string s = "Hello World!")
.method public hidebysig static void SayHello([opt] string s) cil managed
{
    .param [1] = "Hello World!"
+1  A: 

You are looking at the IL for the System.Collections.Generic.Dictionary<> class. The "Dictionary" class name is the string you pass to ModuleBuilder.DefineType().

The .param attribute is generated in C# version 4 or VB.NET for parameters that have a default value. You set it with the ParameterBuilder you get back from MethodBuilder.DefineParameter(). Use the SetConstant() method.

Hans Passant
+2  A: 

I would use the EmitHelper component of the BLToolkit for that purpose. It provides a fluent API resembling IL code, wrapping Reflection.Emit. Example extracted from the linked article:

EmitHelper emit = new AssemblyBuilderHelper("HelloWorld.dll")
    .DefineType  ("Hello", typeof(object), typeof(IHello))
    .DefineMethod(typeof(IHello).GetMethod("SayHello"))
    .Emitter;
emit
    // string.Format("Hello, {0}!", toWhom)
    //
    .ldstr   ("Hello, {0}!")
    .ldarg_1
    .call    (typeof(string), "Format", typeof(string), typeof(object))

    // Console.WriteLine("Hello, World!");
    //
    .call    (typeof(Console), "WriteLine", typeof(string))
    .ret();

Type type = emit.Method.Type.Create();
Buu Nguyen