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