/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeClass.cs
C# | 348 lines | 271 code | 52 blank | 25 comment | 48 complexity | 0c19a864f1cd48b8eb5636f6d1cd8891 MD5 | raw file
1//
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:
9//
10// The above copyright notice and this permission notice shall be
11// included in all copies or substantial portions of the Software.
12//
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.
20//
21// Copyright (C) Lluis Sanchez Gual, 2004
22//
23
24using System;
25using System.IO;
26using System.Collections;
27using System.Reflection;
28using System.Reflection.Emit;
29
30namespace Mono.CodeGeneration
31{
32 public class CodeClass
33 {
34 TypeBuilder typeBuilder;
35 ArrayList customAttributes = new ArrayList ();
36 ArrayList methods = new ArrayList ();
37 ArrayList properties = new ArrayList ();
38 ArrayList fields = new ArrayList ();
39 Hashtable fieldAttributes = new Hashtable ();
40 Type baseType;
41 Type[] interfaces;
42 CodeMethod ctor;
43 CodeMethod cctor;
44 CodeBuilder instanceInit;
45 CodeBuilder classInit;
46 int varId;
47
48 public CodeClass (ModuleBuilder mb, string name)
49 : this (mb, name, TypeAttributes.Public, typeof(object))
50 {
51 }
52
53 public CodeClass (ModuleBuilder mb, string name, Type baseType, params Type[] interfaces)
54 : this (mb, name, TypeAttributes.Public, baseType, interfaces)
55 {
56 }
57
58 public CodeClass (ModuleBuilder mb, string name, TypeAttributes attr, Type baseType, params Type[] interfaces)
59 {
60 typeBuilder = mb.DefineType (name, attr, baseType, interfaces);
61 this.baseType = baseType;
62 this.interfaces = interfaces;
63 }
64
65 public CodeCustomAttribute CreateCustomAttribute (Type attributeType)
66 {
67 return CreateCustomAttribute (attributeType,
68 Type.EmptyTypes, new object [0], new string [0], new object [0]);
69 }
70
71 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, object [] ctorArgs, string [] namedArgFieldNames, object [] namedArgValues)
72 {
73 CodeCustomAttribute cca = CodeCustomAttribute.Create (
74 attributeType, ctorArgTypes, ctorArgs, namedArgFieldNames, namedArgValues);
75
76 typeBuilder.SetCustomAttribute (cca.Builder);
77 customAttributes.Add (cca);
78 return cca;
79 }
80
81 public CodeCustomAttribute CreateCustomAttribute (Type attributeType, Type [] ctorArgTypes, CodeLiteral [] ctorArgs, FieldInfo [] fields, CodeLiteral [] fieldValues)
82 {
83 CodeCustomAttribute cca = CodeCustomAttribute.Create (
84 attributeType, ctorArgTypes, ctorArgs, fields, fieldValues);
85
86 typeBuilder.SetCustomAttribute (cca.Builder);
87 customAttributes.Add (cca);
88 return cca;
89 }
90
91 public CodeProperty CreateProperty (string name, Type returnType, params Type [] parameterTypes)
92 {
93 return CreateProperty (name, returnType, MethodAttributes.Private, parameterTypes);
94 }
95
96 public CodeProperty CreateProperty (string name, Type returnType, MethodAttributes methodAttributes, params Type [] parameterTypes)
97 {
98 CodeProperty prop = new CodeProperty (this, GetPropertyName (name), PropertyAttributes.None, methodAttributes, returnType, parameterTypes);
99 properties.Add (prop);
100 return prop;
101 }
102
103 public CodeMethod CreateMethod (string name, Type returnType, params Type[] parameterTypes)
104 {
105 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public, returnType, parameterTypes);
106 methods.Add (met);
107 return met;
108 }
109
110 public CodeMethod CreateVirtualMethod (string name, Type returnType, params Type[] parameterTypes)
111 {
112 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public | MethodAttributes.Virtual, returnType, parameterTypes);
113 methods.Add (met);
114 return met;
115 }
116
117 public CodeMethod CreateStaticMethod (string name, Type returnType, params Type[] parameterTypes)
118 {
119 CodeMethod met = new CodeMethod (this, GetMethodName (name), MethodAttributes.Public | MethodAttributes.Static, returnType, parameterTypes);
120 methods.Add (met);
121 return met;
122 }
123
124 public CodeMethod CreateMethod (string name, MethodAttributes attributes, Type returnType, params Type[] parameterTypes)
125 {
126 CodeMethod met = new CodeMethod (this, GetMethodName (name), attributes, returnType, parameterTypes);
127 methods.Add (met);
128 return met;
129 }
130
131 public CodeMethod GetDefaultConstructor ()
132 {
133 if (ctor != null) return ctor;
134 ctor = CreateConstructor (MethodAttributes.Public, Type.EmptyTypes);
135 return ctor;
136 }
137
138 public CodeMethod CreateConstructor (params Type[] parameters)
139 {
140 return CreateConstructor (MethodAttributes.Private, parameters);
141 }
142
143 public CodeMethod CreateConstructor (MethodAttributes attributes, params Type[] parameters)
144 {
145 if (ctor != null) return ctor;
146 ctor = CodeMethod.DefineConstructor (this, attributes, parameters);
147 methods.Add (ctor);
148 CodeBuilder cb = GetInstanceInitBuilder ();
149 ctor.CodeBuilder.CurrentBlock.Add (cb.CurrentBlock);
150 return ctor;
151 }
152
153 public CodeMethod GetStaticConstructor ()
154 {
155 if (cctor != null) return cctor;
156 cctor = CodeMethod.DefineConstructor (this, MethodAttributes.Public | MethodAttributes.Static, Type.EmptyTypes);
157 methods.Add (cctor);
158 CodeBuilder cb = GetClassInitBuilder ();
159 cctor.CodeBuilder.CurrentBlock.Add (cb.CurrentBlock);
160 return cctor;
161 }
162
163 public CodeMethod ImplementMethod (Type baseType, string methodName)
164 {
165 MethodInfo basem = baseType.GetMethod (methodName);
166 return ImplementMethod (baseType, basem);
167 }
168
169 public CodeMethod ImplementMethod (MethodInfo basem)
170 {
171 return ImplementMethod (basem.DeclaringType, basem);
172 }
173
174 public CodeMethod ImplementMethod (Type baseType, MethodInfo basem)
175 {
176 ParameterInfo[] pinfos = basem.GetParameters ();
177 Type[] pars = new Type[pinfos.Length];
178 for (int n=0; n<pinfos.Length; n++)
179 pars[n] = pinfos[n].ParameterType;
180
181 CodeMethod met = CodeMethod.DefineMethod (this, basem.Name, MethodAttributes.Public | MethodAttributes.Virtual, basem.ReturnType, pars);
182 typeBuilder.DefineMethodOverride (met.MethodInfo, basem);
183 methods.Add (met);
184 return met;
185 }
186
187 public CodeFieldReference DefineField (string name, Type type, params CodeCustomAttribute [] customAttributes)
188 {
189 return DefineField (GetFieldName (name), type, FieldAttributes.Public, null, customAttributes);
190 }
191
192 public CodeFieldReference DefineStaticField (CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
193 {
194 return DefineField (GetFieldName (null), initialValue.GetResultType(), FieldAttributes.Public | FieldAttributes.Static, initialValue, customAttributes);
195 }
196
197 public CodeFieldReference DefineStaticField (string name, Type type, CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
198 {
199 return DefineField (GetFieldName (name), type, FieldAttributes.Public | FieldAttributes.Static, initialValue, customAttributes);
200 }
201
202 public CodeFieldReference DefineField (string name, Type type, FieldAttributes attrs, CodeExpression initialValue, params CodeCustomAttribute [] customAttributes)
203 {
204 FieldBuilder fb = typeBuilder.DefineField (GetFieldName (name), type, attrs);
205 foreach (CodeCustomAttribute a in customAttributes)
206 fb.SetCustomAttribute (a.Builder);
207 fieldAttributes [fb] = new ArrayList (customAttributes);
208 fields.Add (fb);
209 CodeFieldReference fr;
210 if ((attrs & FieldAttributes.Static) != 0)
211 fr = new CodeFieldReference (fb);
212 else
213 fr = new CodeFieldReference (new CodeArgumentReference (TypeBuilder, 0, "this"), fb);
214
215 if (null != (object) initialValue) {
216 CodeBuilder cb = (attrs & FieldAttributes.Static) == 0 ? GetInstanceInitBuilder () : GetClassInitBuilder ();
217 cb.Assign (fr, initialValue);
218 }
219 return fr;
220 }
221
222 public TypeBuilder TypeBuilder
223 {
224 get { return typeBuilder; }
225 }
226
227 private CodeBuilder GetInstanceInitBuilder ()
228 {
229 if (instanceInit != null) return instanceInit;
230 instanceInit = new CodeBuilder (this);
231 return instanceInit;
232 }
233
234 private CodeBuilder GetClassInitBuilder ()
235 {
236 if (classInit != null) return classInit;
237 classInit = new CodeBuilder (this);
238 return classInit;
239 }
240
241 private string GetFieldName (string name)
242 {
243 if (name == null) return "__field_" + (varId++);
244 else return name;
245 }
246
247 private string GetMethodName (string name)
248 {
249 if (name == null) return "__Method_" + (varId++);
250 else return name;
251 }
252
253 private string GetPropertyName (string name)
254 {
255 if (name == null) return "__Property_" + (varId++);
256 else return name;
257 }
258
259 public string PrintCode ()
260 {
261 StringWriter sw = new StringWriter ();
262 CodeWriter cw = new CodeWriter (sw);
263 PrintCode (cw);
264 return sw.ToString ();
265 }
266
267 public void PrintCode (CodeWriter cw)
268 {
269 for (int n=0; n<customAttributes.Count; n++) {
270 CodeCustomAttribute cca = customAttributes [n] as CodeCustomAttribute;
271 if (n > 0) cw.WriteLine ("");
272 cca.PrintCode (cw);
273 }
274
275/* if ((typeBuilder.Attributes & TypeAttributes.Abstract) != 0) cw.Write ("abstract ");
276 if ((typeBuilder.Attributes & TypeAttributes.NestedAssembly) != 0) cw.Write ("internal ");
277 if ((typeBuilder.Attributes & TypeAttributes.NestedPrivate) != 0) cw.Write ("private ");
278*/ if ((typeBuilder.Attributes & TypeAttributes.Public) != 0) cw.Write ("public ");
279 cw.Write ("class ").Write (typeBuilder.Name);
280
281 bool dots = false;
282 if (baseType != null && baseType != typeof(object)) {
283 cw.Write (" : " + baseType);
284 dots = true;
285 }
286
287 if (interfaces != null && interfaces.Length > 0) {
288 if (!dots) cw.Write (" : ");
289 else cw.Write (", ");
290 for (int n=0; n<interfaces.Length; n++) {
291 if (n > 0) cw.Write (", ");
292 cw.Write (interfaces[n].ToString ());
293 }
294 }
295
296 cw.EndLine ().WriteLineInd ("{");
297
298 foreach (FieldInfo f in fields) {
299 cw.BeginLine ();
300 ArrayList atts = (ArrayList) fieldAttributes [f];
301 foreach (CodeCustomAttribute a in atts)
302 a.PrintCode (cw);
303 if ((f.Attributes & FieldAttributes.Static) != 0)
304 cw.Write ("static ");
305 cw.Write (f.FieldType.Name + " ");
306 cw.Write (f.Name + ";");
307 cw.EndLine ();
308 cw.WriteLine ("");
309 }
310
311 for (int n=0; n<properties.Count; n++) {
312 CodeProperty prop = properties [n] as CodeProperty;
313 if (n > 0) cw.WriteLine ("");
314 prop.PrintCode (cw);
315 }
316
317 for (int n=0; n<methods.Count; n++) {
318 CodeMethod met = methods[n] as CodeMethod;
319 if (n > 0) cw.WriteLine ("");
320 met.PrintCode (cw);
321 }
322 cw.WriteLineUnind ("}");
323 }
324
325 public Type CreateType ()
326 {
327 if (ctor == null)
328 ctor = GetDefaultConstructor ();
329
330 foreach (CodeProperty prop in properties)
331 prop.Generate ();
332
333 foreach (CodeMethod met in methods)
334 met.Generate ();
335
336 Type t = typeBuilder.CreateType ();
337
338 foreach (CodeMethod met in methods)
339 met.UpdateMethodBase (t);
340
341 foreach (CodeProperty prop in properties)
342 prop.UpdatePropertyInfo (t);
343
344 return t;
345 }
346 }
347}
348