2 // Permission is hereby granted, free of charge, to any person obtaining
3 // a copy of this software and associated documentation files (the
4 // "Software"), to deal in the Software without restriction, including
5 // without limitation the rights to use, copy, modify, merge, publish,
6 // distribute, sublicense, and/or sell copies of the Software, and to
7 // permit persons to whom the Software is furnished to do so, subject to
8 // the following conditions:
10 // The above copyright notice and this permission notice shall be
11 // included in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 // Copyright (C) Lluis Sanchez Gual, 2004
27 using System.Collections;
28 using System.Reflection;
29 using System.Reflection.Emit;
31 namespace Mono.CodeGeneration
33 public class CodeClass
35 TypeBuilder typeBuilder;
36 ArrayList customAttributes = new ArrayList ();
37 ArrayList methods = new ArrayList ();
38 ArrayList properties = new ArrayList ();
39 ArrayList fields = new ArrayList ();
40 Hashtable fieldAttributes = new Hashtable ();
45 CodeBuilder instanceInit;
46 CodeBuilder classInit;
49 public CodeClass (ModuleBuilder mb, string name)
50 : this (mb, name, TypeAttributes.Public, typeof(object))
54 public CodeClass (ModuleBuilder mb, string name, Type baseType, params Type[] interfaces)
55 : this (mb, name, TypeAttributes.Public, baseType, interfaces)
59 public CodeClass (ModuleBuilder mb, string name, TypeAttributes attr, Type baseType, params Type[] interfaces)
61 typeBuilder = mb.DefineType (name, attr, baseType, interfaces);
62 this.baseType = baseType;
63 this.interfaces = interfaces;
66 public CodeCustomAttribute CreateCustomAttribute (Type attributeType)
68 return CreateCustomAttribute (attributeType,
69 Type.EmptyTypes, new object [0], new string [0], new object [0]);
72 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues)
74 CodeCustomAttribute cca = CodeCustomAttribute.Create (
75 attributeType, ctorArgTypes, ctorArgs, namedArgFieldNames, namedArgValues);
77 typeBuilder.SetCustomAttribute (cca.Builder);
78 customAttributes.Add (cca);
82 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues)
84 CodeCustomAttribute cca = CodeCustomAttribute.Create (
85 attributeType, ctorArgTypes, ctorArgs, fields, fieldValues);
87 typeBuilder.SetCustomAttribute (cca.Builder);
88 customAttributes.Add (cca);
92 public CodeProperty CreateProperty (string name, Type returnType, params Type [] parameterTypes)
94 return CreateProperty (name, returnType, MethodAttributes.Private, parameterTypes);
97 public CodeProperty CreateProperty (string name, Type returnType, MethodAttributes methodAttributes, params Type [] parameterTypes)
99 CodeProperty prop = new CodeProperty (this, GetPropertyName (name), PropertyAttributes.None, methodAttributes, returnType, parameterTypes);
100 properties.Add (prop);
104 public CodeMethod CreateMethod (string name, Type returnType, params Type[] parameterTypes)
106 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public, returnType, parameterTypes);
111 public CodeMethod CreateVirtualMethod (string name, Type returnType, params Type[] parameterTypes)
113 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public | MethodAttributes.Virtual, returnType, parameterTypes);
118 public CodeMethod CreateStaticMethod (string name, Type returnType, params Type[] parameterTypes)
120 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public | MethodAttributes.Static, returnType, parameterTypes);
125 public CodeMethod CreateMethod (string name, MethodAttributes attributes, Type returnType, params Type[] parameterTypes)
127 CodeMethod met = new CodeMethod (this, GetMethodName (name), attributes, returnType, parameterTypes);
132 public CodeMethod GetDefaultConstructor ()
134 if (ctor != null) return ctor;
135 ctor = CreateConstructor (MethodAttributes.Public, Type.EmptyTypes);
139 public CodeMethod CreateConstructor (params Type[] parameters)
141 return CreateConstructor (MethodAttributes.Private, parameters);
144 public CodeMethod CreateConstructor (MethodAttributes attributes, params Type[] parameters)
146 if (ctor != null) return ctor;
147 ctor = CodeMethod.DefineConstructor (this, attributes, parameters);
149 CodeBuilder cb = GetInstanceInitBuilder ();
150 ctor.CodeBuilder.CurrentBlock.Add (cb.CurrentBlock);
154 public CodeMethod GetStaticConstructor ()
156 if (cctor != null) return cctor;
157 cctor = CodeMethod.DefineConstructor (this, MethodAttributes.Public | MethodAttributes.Static, Type.EmptyTypes);
159 CodeBuilder cb = GetClassInitBuilder ();
160 cctor.CodeBuilder.CurrentBlock.Add (cb.CurrentBlock);
164 public CodeMethod ImplementMethod (Type baseType, string methodName)
166 MethodInfo basem = baseType.GetMethod (methodName);
167 return ImplementMethod (baseType, basem);
170 public CodeMethod ImplementMethod (MethodInfo basem)
172 return ImplementMethod (basem.DeclaringType, basem);
175 public CodeMethod ImplementMethod (Type baseType, MethodInfo basem)
177 ParameterInfo[] pinfos = basem.GetParameters ();
178 Type[] pars = new Type[pinfos.Length];
179 for (int n=0; n<pinfos.Length; n++)
180 pars[n] = pinfos[n].ParameterType;
182 CodeMethod met = CodeMethod.DefineMethod (this, basem.Name, MethodAttributes.Public | MethodAttributes.Virtual, basem.ReturnType, pars);
183 typeBuilder.DefineMethodOverride (met.MethodInfo, basem);
188 public CodeFieldReference DefineField (string name, Type type, params CodeCustomAttribute [] customAttributes)
190 return DefineField (GetFieldName (name), type, FieldAttributes.Public, null, customAttributes);
193 public CodeFieldReference DefineStaticField (CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
195 return DefineField (GetFieldName (null), initialValue.GetResultType(), FieldAttributes.Public | FieldAttributes.Static, initialValue, customAttributes);
198 public CodeFieldReference DefineStaticField (string name, Type type, CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
200 return DefineField (GetFieldName (name), type, FieldAttributes.Public | FieldAttributes.Static, initialValue, customAttributes);
203 public CodeFieldReference DefineField (string name, Type type, FieldAttributes attrs, CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
205 FieldBuilder fb = typeBuilder.DefineField (GetFieldName (name), type, attrs);
206 foreach (CodeCustomAttribute a in customAttributes)
207 fb.SetCustomAttribute (a.Builder);
208 fieldAttributes [fb] = new ArrayList (customAttributes);
210 CodeFieldReference fr;
211 if ((attrs & FieldAttributes.Static) != 0)
212 fr = new CodeFieldReference (fb);
214 fr = new CodeFieldReference (new CodeArgumentReference (TypeBuilder, 0, "this"), fb);
216 if (null != (object) initialValue) {
217 CodeBuilder cb = (attrs & FieldAttributes.Static) == 0 ? GetInstanceInitBuilder () : GetClassInitBuilder ();
218 cb.Assign (fr, initialValue);
223 public TypeBuilder TypeBuilder
225 get { return typeBuilder; }
228 private CodeBuilder GetInstanceInitBuilder ()
230 if (instanceInit != null) return instanceInit;
231 instanceInit = new CodeBuilder (this);
235 private CodeBuilder GetClassInitBuilder ()
237 if (classInit != null) return classInit;
238 classInit = new CodeBuilder (this);
242 private string GetFieldName (string name)
244 if (name == null) return "__field_" + (varId++);
248 private string GetMethodName (string name)
250 if (name == null) return "__Method_" + (varId++);
254 private string GetPropertyName (string name)
256 if (name == null) return "__Property_" + (varId++);
260 public string PrintCode ()
262 StringWriter sw = new StringWriter ();
263 CodeWriter cw = new CodeWriter (sw);
265 return sw.ToString ();
268 public void PrintCode (CodeWriter cw)
270 for (int n=0; n<customAttributes.Count; n++) {
271 CodeCustomAttribute cca = customAttributes [n] as CodeCustomAttribute;
272 if (n > 0) cw.WriteLine ("");
276 /* if ((typeBuilder.Attributes & TypeAttributes.Abstract) != 0) cw.Write ("abstract ");
277 if ((typeBuilder.Attributes & TypeAttributes.NestedAssembly) != 0) cw.Write ("internal ");
278 if ((typeBuilder.Attributes & TypeAttributes.NestedPrivate) != 0) cw.Write ("private ");
279 */ if ((typeBuilder.Attributes & TypeAttributes.Public) != 0) cw.Write ("public ");
280 cw.Write ("class ").Write (typeBuilder.Name);
283 if (baseType != null && baseType != typeof(object)) {
284 cw.Write (" : " + baseType);
288 if (interfaces != null && interfaces.Length > 0) {
289 if (!dots) cw.Write (" : ");
290 else cw.Write (", ");
291 for (int n=0; n<interfaces.Length; n++) {
292 if (n > 0) cw.Write (", ");
293 cw.Write (interfaces[n].ToString ());
297 cw.EndLine ().WriteLineInd ("{");
299 foreach (FieldInfo f in fields) {
301 ArrayList atts = (ArrayList) fieldAttributes [f];
302 foreach (CodeCustomAttribute a in atts)
304 if ((f.Attributes & FieldAttributes.Static) != 0)
305 cw.Write ("static ");
306 cw.Write (f.FieldType.Name + " ");
307 cw.Write (f.Name + ";");
312 for (int n=0; n<properties.Count; n++) {
313 CodeProperty prop = properties [n] as CodeProperty;
314 if (n > 0) cw.WriteLine ("");
318 for (int n=0; n<methods.Count; n++) {
319 CodeMethod met = methods[n] as CodeMethod;
320 if (n > 0) cw.WriteLine ("");
323 cw.WriteLineUnind ("}");
326 public Type CreateType ()
329 ctor = GetDefaultConstructor ();
331 foreach (CodeProperty prop in properties)
334 foreach (CodeMethod met in methods)
337 Type t = typeBuilder.CreateType ();
339 foreach (CodeMethod met in methods)
340 met.UpdateMethodBase (t);
342 foreach (CodeProperty prop in properties)
343 prop.UpdatePropertyInfo (t);