PageRenderTime 13ms CodeModel.GetById 1ms app.highlight 9ms 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
 50#region Using directives
 51using System;
 52using System.Collections.Generic;
 53using System.Linq;
 54using System.Reflection;
 55using System.Reflection.Emit;
 56using System.Text;
 57#endregion
 58
 59
 60class Program
 61{
 62    static void Main(string[] args)
 63    {
 64        /////////////////////////////////////////////////////////////////////
 65        // Define the assembly and the module.
 66        // 
 67
 68        AppDomain appDomain = AppDomain.CurrentDomain;
 69        AssemblyName assemblyName = new AssemblyName("EmittedAssembly");
 70        AssemblyBuilder assembly = appDomain.DefineDynamicAssembly(
 71            assemblyName, AssemblyBuilderAccess.RunAndSave);
 72
 73        // An assembly is made up of executable modules. For a single-module
 74        // assembly, the module name and file name are the same as the 
 75        // assembly name. 
 76
 77        ModuleBuilder module = assembly.DefineDynamicModule(
 78            assemblyName.Name, assemblyName.Name + ".dll");
 79
 80
 81        /////////////////////////////////////////////////////////////////////
 82        // Declare the types (classes).
 83        // 
 84
 85        // Declare the class "ClassA"
 86        TypeBuilder classA = module.DefineType("ClassA", TypeAttributes.Public);
 87        // Declare the class "ClassB"
 88        TypeBuilder classB = module.DefineType("ClassB", TypeAttributes.Public);
 89
 90
 91        /////////////////////////////////////////////////////////////////////
 92        // Define the type, ClassA.
 93        // 
 94
 95        #region Constructors
 96
 97        #endregion
 98
 99        #region Fields
100
101        // Define the fields stringField, classBField
102        FieldBuilder stringField = classA.DefineField("stringField",
103            typeof(string), FieldAttributes.Private);
104        FieldBuilder classBField = classA.DefineField("classBField",
105            classB, FieldAttributes.Public);
106
107        #endregion
108
109        #region Properties
110
111        // Define the property ClassBProperty
112        PropertyBuilder classBProperty = classA.DefineProperty(
113            "ClassBProperty", PropertyAttributes.None, classB, null);
114
115        // The special set of attributes for the property set&get methods
116        MethodAttributes getSetAttr = MethodAttributes.Public |
117            MethodAttributes.SpecialName | MethodAttributes.HideBySig;
118
119        // Define the "get" accessor method for ClassBProperty
120        MethodBuilder classBGetProp = classA.DefineMethod(
121            "get_ClassBProperty", getSetAttr, classB, Type.EmptyTypes);
122        ILGenerator classBGetIL = classBGetProp.GetILGenerator();
123        classBGetIL.Emit(OpCodes.Ldarg_0);
124        classBGetIL.Emit(OpCodes.Ldfld, classBField);
125        classBGetIL.Emit(OpCodes.Ret);
126
127        // Define the "set" accessor method for ClassBProperty
128        MethodBuilder classBSetProp = classA.DefineMethod(
129            "set_ClassBProperty", getSetAttr, null, new Type[] { classB });
130        ILGenerator sampleSetIL = classBSetProp.GetILGenerator();
131        sampleSetIL.Emit(OpCodes.Ldarg_0);
132        sampleSetIL.Emit(OpCodes.Ldarg_1);
133        sampleSetIL.Emit(OpCodes.Stfld, classBField);
134        sampleSetIL.Emit(OpCodes.Ret);
135
136        // Map the get&set methods to PropertyBuilder
137        classBProperty.SetGetMethod(classBGetProp);
138        classBProperty.SetSetMethod(classBSetProp);
139
140        #endregion
141
142        #region Methods
143
144        // Define a method that uses the classBField
145        MethodBuilder classAMethod = classA.DefineMethod("ClassAMethod", 
146            MethodAttributes.Public);
147
148        // Define the list generics and ienumerable generic
149        Type listOf = typeof(List<>);
150        Type enumOf = typeof(IEnumerable<>);
151        Type listOfClassA = listOf.MakeGenericType(classA);
152        Type enumOfClassA = enumOf.MakeGenericType(classA);
153
154        // Define the method, ClassBMethod, for ClassB
155        MethodBuilder classBMethod = classB.DefineMethod("ClassBMethod", 
156            MethodAttributes.Public, typeof(void), new Type[] { listOfClassA });
157        classBMethod.DefineParameter(1, ParameterAttributes.None, "list");
158
159        // Write the body of ClassAMethod that calls ClassBMethod
160        ILGenerator ilgenA = classAMethod.GetILGenerator();
161        ilgenA.Emit(OpCodes.Nop);
162        ilgenA.Emit(OpCodes.Ldarg_0);
163        ilgenA.Emit(OpCodes.Ldfld, classBField);
164        ilgenA.Emit(OpCodes.Ldnull);
165        ilgenA.Emit(OpCodes.Callvirt, classBMethod);
166        ilgenA.Emit(OpCodes.Ret);
167
168        #endregion
169
170
171        /////////////////////////////////////////////////////////////////////
172        // Define the type, ClassB.
173        // 
174
175        #region Constructors
176
177        #endregion
178
179        #region Fields
180
181        // Define the fields classAField, classAList
182        FieldBuilder classAField = classB.DefineField("classAField", classA, 
183            FieldAttributes.Private);
184        FieldBuilder classAList = classB.DefineField("classAList", listOfClassA, 
185            FieldAttributes.Private);
186
187        #endregion
188
189        #region Properties
190
191        // Define the property ClassAList
192        PropertyBuilder classAListProperty = classB.DefineProperty(
193            "ClassAList", PropertyAttributes.None, listOfClassA, null);
194
195        // Define the "get" accessor method for ClassAList
196        MethodBuilder listGetProp = classB.DefineMethod("get_ClassAList",
197            getSetAttr, listOfClassA, null);
198        ILGenerator listGetIL = listGetProp.GetILGenerator();
199        listGetIL.Emit(OpCodes.Ldarg_0);
200        listGetIL.Emit(OpCodes.Ldfld, classAList);
201        listGetIL.Emit(OpCodes.Ret);
202
203        // Define the "set" accessor method for ClassAList
204        MethodInfo addRangeBaseMethod = listOf.GetMethod("AddRange");
205        MethodInfo addRangeMethod = TypeBuilder.GetMethod(
206            listOfClassA, addRangeBaseMethod);
207
208        MethodBuilder listSetProp = classB.DefineMethod("set_ClassAList",
209            getSetAttr, null, new Type[] { listOfClassA });
210        ILGenerator listSetIL = listSetProp.GetILGenerator();
211        listSetIL.Emit(OpCodes.Nop);
212        listSetIL.Emit(OpCodes.Ldarg_0);
213        listSetIL.Emit(OpCodes.Ldfld, classAList);
214        listSetIL.Emit(OpCodes.Ldarg_1);
215        listSetIL.Emit(OpCodes.Callvirt, addRangeMethod);
216        listSetIL.Emit(OpCodes.Ret);
217
218        classAListProperty.SetGetMethod(listGetProp);
219        classAListProperty.SetSetMethod(listSetProp);
220
221        #endregion
222
223        #region Methods
224
225        // Write the body of ClassBMethod that calls ClassAMethod
226        ILGenerator ilgenB = classBMethod.GetILGenerator();
227        ilgenB.Emit(OpCodes.Nop);
228        ilgenB.Emit(OpCodes.Ldarg_0);
229        ilgenB.Emit(OpCodes.Ldfld, classAField);
230        ilgenB.Emit(OpCodes.Callvirt, classAMethod);
231        ilgenB.Emit(OpCodes.Ret);
232
233        #endregion
234
235
236        /////////////////////////////////////////////////////////////////////
237        // Create the types.
238        // 
239
240        classA.CreateType();
241        classB.CreateType();
242
243
244        /////////////////////////////////////////////////////////////////////
245        // Save the assembly.
246        // 
247
248        assembly.Save(assemblyName.Name + ".dll");
249    }
250}