Reflection Emit – Create Dynamic Assembly

/**********************************************************************
 * Create Dynamic Assembly
 * Author: Yin Yang <yinyang.it@gmail.com>
 * https://yinyangit.wordpress.com
 * Date: 21 March 2011
 *
 **********************************************************************/
using System;
using System.Reflection;
using System.Reflection.Emit;

namespace ConsoleApplication1
{
    class ReflectionEmit
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Test the Rectangle class... ");

            Console.Write("Length: ");
            int length = int.Parse(Console.ReadLine());
            Console.Write("Width: ");
            int width = int.Parse(Console.ReadLine());

            Type t = CreateDynamicAssembly();

            object obj = Activator.CreateInstance(t, length, width);
            object ret = t.InvokeMember("CalculateArea", BindingFlags.InvokeMethod, null, obj, null);

            Console.WriteLine("Area = " + ret);
            Console.Read();
        }

        public static Type CreateDynamicAssembly()
        {

            AssemblyName asmName = new AssemblyName("RectangleTest");

            AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);

            ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule("RectangrtyleTest", "RectangleTest.exe");

            TypeBuilder typeBuilder = modBuilder.DefineType("Rectangle", TypeAttributes.Public);

            FieldBuilder field1 = typeBuilder.DefineField("_length", typeof(Int32), FieldAttributes.PrivateScope);
            FieldBuilder field2 = typeBuilder.DefineField("_width", typeof(Int32), FieldAttributes.PrivateScope);

            MethodBuilder mCalArea = typeBuilder.DefineMethod("CalculateArea", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(Int32), null);

            ILGenerator ilGen = mCalArea.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, field1);
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, field2);
            ilGen.Emit(OpCodes.Mul);
            ilGen.Emit(OpCodes.Ret);

            // Property Length
            PropertyBuilder prop1 = typeBuilder.DefineProperty("Length", PropertyAttributes.None, typeof(System.Int32), null);
            // Getter
            MethodBuilder mGetter1 = typeBuilder.DefineMethod("get_Length", MethodAttributes.Public, typeof(System.Int32), Type.EmptyTypes);

            ilGen = mGetter1.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, field1);
            ilGen.Emit(OpCodes.Ret);

            // Setter
            MethodBuilder mSetter1 = typeBuilder.DefineMethod("set_Length", MethodAttributes.Public, null, new Type[] { typeof(System.Int32) });

            ilGen = mSetter1.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Stfld, field1);
            ilGen.Emit(OpCodes.Ret);

            prop1.SetGetMethod(mGetter1);
            prop1.SetSetMethod(mSetter1);

            // Property Width
            PropertyBuilder prop2 = typeBuilder.DefineProperty("Width", PropertyAttributes.None, typeof(System.Int32), null);
            //Getter
            MethodBuilder mGetter2 = typeBuilder.DefineMethod("get_Width", MethodAttributes.Public |
                MethodAttributes.SpecialName |
                MethodAttributes.HideBySig, typeof(System.Int32), Type.EmptyTypes);
            ilGen = mGetter2.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldfld, field2);
            ilGen.Emit(OpCodes.Ret);

            //Setter
            MethodBuilder mSetter2 = typeBuilder.DefineMethod("set_Width", MethodAttributes.Public |
                MethodAttributes.SpecialName |
                MethodAttributes.HideBySig, null, new Type[] { typeof(System.Int32) });

            ilGen = mSetter2.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Stfld, field2);
            ilGen.Emit(OpCodes.Ret);

            prop2.SetGetMethod(mGetter2);
            prop2.SetSetMethod(mSetter2);

            ConstructorBuilder conBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Int32), typeof(Int32) });

            ConstructorInfo conInfo = typeof(object).GetConstructor(new Type[] { });

            ilGen = conBuilder.GetILGenerator();

            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Call, conInfo);
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Call, mSetter1);
            ilGen.Emit(OpCodes.Ldarg_0);
            ilGen.Emit(OpCodes.Ldarg_2);
            ilGen.Emit(OpCodes.Call, mSetter2);
            ilGen.Emit(OpCodes.Ret);

            MethodBuilder mMain = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard);

            ilGen = mMain.GetILGenerator();
            ilGen.DeclareLocal(typeof(int));

            ilGen.Emit(OpCodes.Ldc_I4, 5);
            ilGen.Emit(OpCodes.Ldc_I4, 4);
            ilGen.Emit(OpCodes.Newobj, conBuilder);

            ilGen.Emit(OpCodes.Callvirt, mCalArea);
            ilGen.Emit(OpCodes.Stloc_0);
            ilGen.Emit(OpCodes.Ldstr, "Area of rectangle is {0}");
            ilGen.Emit(OpCodes.Ldloc_0);

            ilGen.Emit(OpCodes.Box, typeof(Int32));
            MethodInfo wl = typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(object) });
            ilGen.Emit(OpCodes.Call, wl);
            ilGen.Emit(OpCodes.Ret);

            Type t = typeBuilder.CreateType();

            asmBuilder.SetEntryPoint(mMain);
            asmBuilder.Save("RectangleTest.exe");

            return t;
        }
    }
}

Test:

Reflection Emit - Test

Bài viết:
.Net – Kĩ thuật Reflection Emit trong C#

https://yinyangit.wordpress.com

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s