/********************************************************************** * 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:
Bài viết:
.Net – Kĩ thuật Reflection Emit trong C#
https://yinyangit.wordpress.com
Advertisements