PageRenderTime 77ms CodeModel.GetById 59ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System.ServiceModel/Mono.CodeGeneration/CodeClass.cs

https://bitbucket.org/luobailiang/mono
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