开发者

In general, how to convert ilasm syntax into Reflection.Emit calls?

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开发者_Go百科`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!"


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();


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.


Since no one could answer the question, I conclude no documentation exists to show the relationship between ilasm syntax and Reflection.Emit calls.

As a side note, I've found that it's usually better to create code at run-time using RunSharp than Reflection.Emit. When I have time I'll try to figure out the new version of Cecil.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜