微软最近貌似要在 SilverLight 和 DLR 上下狠功夫,动态语言的流行和广泛使用的趋势已经是必然,无聊的我浏览了一下DLR的源代码,一堆堆的 ILGenerator.Emit 语句映入眼帘,写过 .NET 语言编译器或者玩过 MSIL 的同学们肯定对这些东西颇为熟悉,如果你恨透了这一行行的 Emit(OpCodes....)...  那你一定要试试 BLToolkit 中的 EmitHelper 以及其他的一些 Reflection 相关的东西,下面的代码使用了 BLToolkit.Reflection.EmitHelper,啊..这才是给人读的代码啊.....

Title

using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

using System.Reflection;

using System.Reflection.Emit;

 

using BLToolkit.Reflection;

using BLToolkit.Reflection.Emit;

 

namespace Adrian.Reflection

{

    class Program

    {

        static void Main(string[] args)

        {

            string asName = "hw.exe";

            AssemblyBuilderHelper assem = new AssemblyBuilderHelper(asName);

            TypeBuilderHelper type = assem.DefineType("Emit.Program", TypeAttributes.Public, t.Object);

 

            MethodBuilderHelper add = type.DefineMethod("Add", MethodAttributes.Public | MethodAttributes.Static, t.Int32, new Type[] { t.Int32Array });

            add.MethodBuilder.DefineParameter(1, ParameterAttributes.None, "nums");

            EmitHelper addIL = add.Emitter;

            addIL.DeclareLocal(t.Int32);

            addIL.DeclareLocal(t.Int32);

 

            Label cmp = addIL.DefineLabel();

            Label end = addIL.DefineLabel();

 

            addIL

            .ldc_i4_0

            .stloc_0

            .ldc_i4_0

            .stloc_1

            .MarkLabel(cmp)

            .ldloc_1

            .ldarg_0

            .ldlen

            .conv_i4

            .clt

            .brfalse_s(end)

            .ldloc_0

            .ldarg_0

            .ldloc_1

            .ldelem_i4

            .add

            .stloc_0

            .ldloc_1

            .ldc_i4_1

            .add

            .stloc_1

            .br_s(cmp)

            .MarkLabel(end)

            .ldloc_0

            .ret();

 

 

            MethodBuilderHelper main = type.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, t.Void, new Type[] { t.StringArray });

            main.MethodBuilder.DefineParameter(1, ParameterAttributes.None, "args");

            EmitHelper mainIL = main.Emitter;

            mainIL.DeclareLocal(t.Int32Array);

 

            mainIL

            .ldc_i4_3

            .newarr(t.Int32)

            .stloc_0

            .ldloc_0

            .ldc_i4_0

            .ldc_i4_1

            .stelem_i4

            .ldloc_0

            .ldc_i4_1

            .ldc_i4_2

            .stelem_i4

            .ldloc_0

            .ldc_i4_2

            .ldc_i4_3

            .stelem_i4

            .ldloc_0

            .call(add)

            .call(typeof(Console), "WriteLine", t.Int32)

            .ret();

 

            type.Create();

            assem.AssemblyBuilder.SetEntryPoint(main, PEFileKinds.ConsoleApplication);

            assem.Save();

 

            Assembly newAs = Assembly.LoadFile(Path.GetFullPath(asName));

            newAs.EntryPoint.Invoke(null, new object[] { new string[] { } });

        }

    }

 

    class t

    {

        private static Type _int32 = typeof(Int32);

        private static Type _int32Array = typeof(Int32[]);

        private static Type _object = typeof(Object);

        private static Type _void = typeof(void);

        private static Type _string = typeof(String);

        private static Type _stringArray = typeof(String[]);

 

        public static Type StringArray

        {

            get { return t._stringArray; }

        }

 

        public static Type String

        {

            get { return t._string; }

        }

 

        public static Type Void

        {

            get { return t._void; }

        }

 

        public static Type Object

        {

            get { return t._object; }

        }

 

        public static Type Int32Array

        {

            get { return t._int32Array; }

        }

 

        public static Type Int32

        {

            get { return _int32; }

        }

    }

}


中间的那两段 IL 是不是很像Visual C++里的内联汇编?其实 EmitHelper 只是对 ILGenerator 以及所有的 OpCode操作进行了封装,和直接使用 ILGenerator.Emit 是完全等价的, 写起来很有点 Intellisense 的感觉。
废话不说了,BLToolkit 的主页是:http://www.bltoolkit.net/
PS: BLToolkit 是开源的
Posted on 2007-05-07 19:57  Adrian H.  阅读(2410)  评论(4编辑  收藏  举报