CodeClass.cs 11 KB

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