PageRenderTime 66ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Visual Studio 2008/CSEmitAssembly/Program.cs

#
C# | 250 lines | 112 code | 52 blank | 86 comment | 0 complexity | 773230fb3885e55f933341aba4981c4f MD5 | raw file
  1. /****************************** Module Header ******************************\
  2. * Module Name: Program.cs
  3. * Project: CSEmitAssembly
  4. * Copyright (c) Microsoft Corporation.
  5. *
  6. * This example emits these two classes that are mutually referenced.
  7. *
  8. * public class ClassA {
  9. * // Fields
  10. * private ClassB classBField;
  11. * private String stringField;
  12. *
  13. * // Methods
  14. * public void ClassAMethod()
  15. * { this.classBField.ClassBMethod(null); }
  16. *
  17. * // Properties
  18. * public ClassB ClassBProperty {
  19. * get { return this.classBField; }
  20. * set { this.classBField = value; }
  21. * }
  22. * }
  23. *
  24. * public class ClassB {
  25. * // Fields
  26. * private List<ClassA> classAList;
  27. * private ClassA classAField;
  28. *
  29. * // Methods
  30. * public void ClassBMethod(List<ClassA> list) {
  31. * this.classAField.ClassAMethod();
  32. * }
  33. *
  34. * // Properties
  35. * public List<ClassA> ClassAList {
  36. * get { return this.classAList; }
  37. * set { this.classAList.AddRange(value); }
  38. * }
  39. * }
  40. *
  41. * This source is subject to the Microsoft Public License.
  42. * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  43. * All other rights reserved.
  44. *
  45. * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  46. * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  47. * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  48. \***************************************************************************/
  49. #region Using directives
  50. using System;
  51. using System.Collections.Generic;
  52. using System.Linq;
  53. using System.Reflection;
  54. using System.Reflection.Emit;
  55. using System.Text;
  56. #endregion
  57. class Program
  58. {
  59. static void Main(string[] args)
  60. {
  61. /////////////////////////////////////////////////////////////////////
  62. // Define the assembly and the module.
  63. //
  64. AppDomain appDomain = AppDomain.CurrentDomain;
  65. AssemblyName assemblyName = new AssemblyName("EmittedAssembly");
  66. AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(
  67. assemblyName, AssemblyBuilderAccess.RunAndSave);
  68. // An assembly is made up of executable modules. For a single-module
  69. // assembly, the module name and file name are the same as the
  70. // assembly name.
  71. ModuleBuilder module = assembly.DefineDynamicModule(
  72. assemblyName.Name, assemblyName.Name + ".dll");
  73. /////////////////////////////////////////////////////////////////////
  74. // Declare the types (classes).
  75. //
  76. // Declare the class "ClassA"
  77. TypeBuilder classA = module.DefineType("ClassA", TypeAttributes.Public);
  78. // Declare the class "ClassB"
  79. TypeBuilder classB = module.DefineType("ClassB", TypeAttributes.Public);
  80. /////////////////////////////////////////////////////////////////////
  81. // Define the type, ClassA.
  82. //
  83. #region Constructors
  84. #endregion
  85. #region Fields
  86. // Define the fields stringField, classBField
  87. FieldBuilder stringField = classA.DefineField("stringField",
  88. typeof(string), FieldAttributes.Private);
  89. FieldBuilder classBField = classA.DefineField("classBField",
  90. classB, FieldAttributes.Public);
  91. #endregion
  92. #region Properties
  93. // Define the property ClassBProperty
  94. PropertyBuilder classBProperty = classA.DefineProperty(
  95. "ClassBProperty", PropertyAttributes.None, classB, null);
  96. // The special set of attributes for the property set&get methods
  97. MethodAttributes getSetAttr = MethodAttributes.Public |
  98. MethodAttributes.SpecialName | MethodAttributes.HideBySig;
  99. // Define the "get" accessor method for ClassBProperty
  100. MethodBuilder classBGetProp = classA.DefineMethod(
  101. "get_ClassBProperty", getSetAttr, classB, Type.EmptyTypes);
  102. ILGenerator classBGetIL = classBGetProp.GetILGenerator();
  103. classBGetIL.Emit(OpCodes.Ldarg_0);
  104. classBGetIL.Emit(OpCodes.Ldfld, classBField);
  105. classBGetIL.Emit(OpCodes.Ret);
  106. // Define the "set" accessor method for ClassBProperty
  107. MethodBuilder classBSetProp = classA.DefineMethod(
  108. "set_ClassBProperty", getSetAttr, null, new Type[] { classB });
  109. ILGenerator sampleSetIL = classBSetProp.GetILGenerator();
  110. sampleSetIL.Emit(OpCodes.Ldarg_0);
  111. sampleSetIL.Emit(OpCodes.Ldarg_1);
  112. sampleSetIL.Emit(OpCodes.Stfld, classBField);
  113. sampleSetIL.Emit(OpCodes.Ret);
  114. // Map the get&set methods to PropertyBuilder
  115. classBProperty.SetGetMethod(classBGetProp);
  116. classBProperty.SetSetMethod(classBSetProp);
  117. #endregion
  118. #region Methods
  119. // Define a method that uses the classBField
  120. MethodBuilder classAMethod = classA.DefineMethod("ClassAMethod",
  121. MethodAttributes.Public);
  122. // Define the list generics and ienumerable generic
  123. Type listOf = typeof(List<>);
  124. Type enumOf = typeof(IEnumerable<>);
  125. Type listOfClassA = listOf.MakeGenericType(classA);
  126. Type enumOfClassA = enumOf.MakeGenericType(classA);
  127. // Define the method, ClassBMethod, for ClassB
  128. MethodBuilder classBMethod = classB.DefineMethod("ClassBMethod",
  129. MethodAttributes.Public, typeof(void), new Type[] { listOfClassA });
  130. classBMethod.DefineParameter(1, ParameterAttributes.None, "list");
  131. // Write the body of ClassAMethod that calls ClassBMethod
  132. ILGenerator ilgenA = classAMethod.GetILGenerator();
  133. ilgenA.Emit(OpCodes.Nop);
  134. ilgenA.Emit(OpCodes.Ldarg_0);
  135. ilgenA.Emit(OpCodes.Ldfld, classBField);
  136. ilgenA.Emit(OpCodes.Ldnull);
  137. ilgenA.Emit(OpCodes.Callvirt, classBMethod);
  138. ilgenA.Emit(OpCodes.Ret);
  139. #endregion
  140. /////////////////////////////////////////////////////////////////////
  141. // Define the type, ClassB.
  142. //
  143. #region Constructors
  144. #endregion
  145. #region Fields
  146. // Define the fields classAField, classAList
  147. FieldBuilder classAField = classB.DefineField("classAField", classA,
  148. FieldAttributes.Private);
  149. FieldBuilder classAList = classB.DefineField("classAList", listOfClassA,
  150. FieldAttributes.Private);
  151. #endregion
  152. #region Properties
  153. // Define the property ClassAList
  154. PropertyBuilder classAListProperty = classB.DefineProperty(
  155. "ClassAList", PropertyAttributes.None, listOfClassA, null);
  156. // Define the "get" accessor method for ClassAList
  157. MethodBuilder listGetProp = classB.DefineMethod("get_ClassAList",
  158. getSetAttr, listOfClassA, null);
  159. ILGenerator listGetIL = listGetProp.GetILGenerator();
  160. listGetIL.Emit(OpCodes.Ldarg_0);
  161. listGetIL.Emit(OpCodes.Ldfld, classAList);
  162. listGetIL.Emit(OpCodes.Ret);
  163. // Define the "set" accessor method for ClassAList
  164. MethodInfo addRangeBaseMethod = listOf.GetMethod("AddRange");
  165. MethodInfo addRangeMethod = TypeBuilder.GetMethod(
  166. listOfClassA, addRangeBaseMethod);
  167. MethodBuilder listSetProp = classB.DefineMethod("set_ClassAList",
  168. getSetAttr, null, new Type[] { listOfClassA });
  169. ILGenerator listSetIL = listSetProp.GetILGenerator();
  170. listSetIL.Emit(OpCodes.Nop);
  171. listSetIL.Emit(OpCodes.Ldarg_0);
  172. listSetIL.Emit(OpCodes.Ldfld, classAList);
  173. listSetIL.Emit(OpCodes.Ldarg_1);
  174. listSetIL.Emit(OpCodes.Callvirt, addRangeMethod);
  175. listSetIL.Emit(OpCodes.Ret);
  176. classAListProperty.SetGetMethod(listGetProp);
  177. classAListProperty.SetSetMethod(listSetProp);
  178. #endregion
  179. #region Methods
  180. // Write the body of ClassBMethod that calls ClassAMethod
  181. ILGenerator ilgenB = classBMethod.GetILGenerator();
  182. ilgenB.Emit(OpCodes.Nop);
  183. ilgenB.Emit(OpCodes.Ldarg_0);
  184. ilgenB.Emit(OpCodes.Ldfld, classAField);
  185. ilgenB.Emit(OpCodes.Callvirt, classAMethod);
  186. ilgenB.Emit(OpCodes.Ret);
  187. #endregion
  188. /////////////////////////////////////////////////////////////////////
  189. // Create the types.
  190. //
  191. classA.CreateType();
  192. classB.CreateType();
  193. /////////////////////////////////////////////////////////////////////
  194. // Save the assembly.
  195. //
  196. assembly.Save(assemblyName.Name + ".dll");
  197. }
  198. }