LearningEmit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Program.cs 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System;
  2. using System.Reflection;
  3. using System.Reflection.Emit;
  4. namespace EmitCreateMembers
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. // specify a new assembly name
  11. var assemblyName = new AssemblyName("Pets");
  12. // create assembly builder
  13. var assemblyBuilder = AppDomain.CurrentDomain
  14. .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
  15. // create module builder
  16. var moduleBuilder = assemblyBuilder.DefineDynamicModule("PetsModule", "Pets.dll");
  17. // create type builder for a class
  18. var typeBuilder = moduleBuilder.DefineType("Kitty", TypeAttributes.Public);
  19. // then create whole class structure
  20. CreateKittyClassStructure(typeBuilder);
  21. // then create the whole class type
  22. var classType = typeBuilder.CreateType();
  23. // save assembly
  24. assemblyBuilder.Save("Pets.dll");
  25. Console.WriteLine("Hi, Dennis, a Pets assembly has been generated for you.");
  26. Console.ReadLine();
  27. }
  28. private static void CreateKittyClassStructure(TypeBuilder typeBuilder)
  29. {
  30. // ---- define fields ----
  31. var fieldId = typeBuilder.DefineField(
  32. "_id", typeof(int), FieldAttributes.Private);
  33. var fieldName = typeBuilder.DefineField(
  34. "_name", typeof(string), FieldAttributes.Private);
  35. // ---- define costructors ----
  36. Type objType = Type.GetType("System.Object");
  37. ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
  38. Type[] constructorArgs = { typeof(int), typeof(string) };
  39. var constructorBuilder = typeBuilder.DefineConstructor(
  40. MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
  41. ILGenerator ilOfCtor = constructorBuilder.GetILGenerator();
  42. ilOfCtor.Emit(OpCodes.Ldarg_0);
  43. ilOfCtor.Emit(OpCodes.Call, objCtor);
  44. ilOfCtor.Emit(OpCodes.Ldarg_0);
  45. ilOfCtor.Emit(OpCodes.Ldarg_1);
  46. ilOfCtor.Emit(OpCodes.Stfld, fieldId);
  47. ilOfCtor.Emit(OpCodes.Ldarg_0);
  48. ilOfCtor.Emit(OpCodes.Ldarg_2);
  49. ilOfCtor.Emit(OpCodes.Stfld, fieldName);
  50. ilOfCtor.Emit(OpCodes.Ret);
  51. // ---- define properties ----
  52. var methodGetId = typeBuilder.DefineMethod(
  53. "GetId", MethodAttributes.Public, typeof(int), null);
  54. var methodSetId = typeBuilder.DefineMethod(
  55. "SetId", MethodAttributes.Public, null, new Type[] { typeof(int) });
  56. var ilOfGetId = methodGetId.GetILGenerator();
  57. ilOfGetId.Emit(OpCodes.Ldarg_0); // this
  58. ilOfGetId.Emit(OpCodes.Ldfld, fieldId);
  59. ilOfGetId.Emit(OpCodes.Ret);
  60. var ilOfSetId = methodSetId.GetILGenerator();
  61. ilOfSetId.Emit(OpCodes.Ldarg_0); // this
  62. ilOfSetId.Emit(OpCodes.Ldarg_1); // the first one in arguments list
  63. ilOfSetId.Emit(OpCodes.Stfld, fieldId);
  64. ilOfSetId.Emit(OpCodes.Ret);
  65. // create Id property
  66. var propertyId = typeBuilder.DefineProperty(
  67. "Id", PropertyAttributes.None, typeof(int), null);
  68. propertyId.SetGetMethod(methodGetId);
  69. propertyId.SetSetMethod(methodSetId);
  70. var methodGetName = typeBuilder.DefineMethod(
  71. "GetName", MethodAttributes.Public, typeof(string), null);
  72. var methodSetName = typeBuilder.DefineMethod(
  73. "SetName", MethodAttributes.Public, null, new Type[] { typeof(string) });
  74. var ilOfGetName = methodGetName.GetILGenerator();
  75. ilOfGetName.Emit(OpCodes.Ldarg_0); // this
  76. ilOfGetName.Emit(OpCodes.Ldfld, fieldName);
  77. ilOfGetName.Emit(OpCodes.Ret);
  78. var ilOfSetName = methodSetName.GetILGenerator();
  79. ilOfSetName.Emit(OpCodes.Ldarg_0); // this
  80. ilOfSetName.Emit(OpCodes.Ldarg_1); // the first one in arguments list
  81. ilOfSetName.Emit(OpCodes.Stfld, fieldName);
  82. ilOfSetName.Emit(OpCodes.Ret);
  83. // create Name property
  84. var propertyName = typeBuilder.DefineProperty(
  85. "Name", PropertyAttributes.None, typeof(string), null);
  86. propertyName.SetGetMethod(methodGetName);
  87. propertyName.SetSetMethod(methodSetName);
  88. // ---- define methods ----
  89. // create ToString() method
  90. var methodToString = typeBuilder.DefineMethod(
  91. "ToString",
  92. MethodAttributes.Virtual | MethodAttributes.Public,
  93. typeof(string),
  94. null);
  95. var ilOfToString = methodToString.GetILGenerator();
  96. var local = ilOfToString.DeclareLocal(typeof(string)); // create a local variable
  97. ilOfToString.Emit(OpCodes.Ldstr, "Id:[{0}], Name:[{1}]");
  98. ilOfToString.Emit(OpCodes.Ldarg_0); // this
  99. ilOfToString.Emit(OpCodes.Ldfld, fieldId);
  100. ilOfToString.Emit(OpCodes.Box, typeof(int)); // boxing the value type to object
  101. ilOfToString.Emit(OpCodes.Ldarg_0); // this
  102. ilOfToString.Emit(OpCodes.Ldfld, fieldName);
  103. ilOfToString.Emit(OpCodes.Call,
  104. typeof(string).GetMethod("Format",
  105. new Type[] { typeof(string), typeof(object), typeof(object) }));
  106. ilOfToString.Emit(OpCodes.Stloc, local); // set local variable
  107. ilOfToString.Emit(OpCodes.Ldloc, local); // load local variable to stack
  108. ilOfToString.Emit(OpCodes.Ret);
  109. }
  110. }
  111. }