CustomAttributeBuilder.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining
  5. // a copy of this software and associated documentation files (the
  6. // "Software"), to deal in the Software without restriction, including
  7. // without limitation the rights to use, copy, modify, merge, publish,
  8. // distribute, sublicense, and/or sell copies of the Software, and to
  9. // permit persons to whom the Software is furnished to do so, subject to
  10. // the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. //
  23. //
  24. // System.Reflection.Emit/CustomAttributeBuilder.cs
  25. //
  26. // Author:
  27. // Paolo Molaro ([email protected])
  28. //
  29. // (C) 2001 Ximian, Inc. http://www.ximian.com
  30. //
  31. using System;
  32. using System.Reflection;
  33. using System.Reflection.Emit;
  34. using System.Runtime.CompilerServices;
  35. using System.Runtime.InteropServices;
  36. namespace System.Reflection.Emit {
  37. public class CustomAttributeBuilder {
  38. ConstructorInfo ctor;
  39. byte[] data;
  40. internal ConstructorInfo Ctor {
  41. get {return ctor;}
  42. }
  43. internal byte[] Data {
  44. get {return data;}
  45. }
  46. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  47. static extern byte[] GetBlob(Assembly asmb, ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues);
  48. internal CustomAttributeBuilder( ConstructorInfo con, byte[] cdata) {
  49. ctor = con;
  50. data = (byte[])cdata.Clone ();
  51. /* should we check that the user supplied data is correct? */
  52. }
  53. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs)
  54. {
  55. Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
  56. new FieldInfo [0], new object [0]);
  57. }
  58. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  59. FieldInfo[] namedFields, object[] fieldValues)
  60. {
  61. Initialize (con, constructorArgs, new PropertyInfo [0], new object [0],
  62. namedFields, fieldValues);
  63. }
  64. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  65. PropertyInfo[] namedProperties, object[] propertyValues)
  66. {
  67. Initialize (con, constructorArgs, namedProperties, propertyValues, new FieldInfo [0],
  68. new object [0]);
  69. }
  70. public CustomAttributeBuilder( ConstructorInfo con, object[] constructorArgs,
  71. PropertyInfo[] namedProperties, object[] propertyValues,
  72. FieldInfo[] namedFields, object[] fieldValues)
  73. {
  74. Initialize (con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
  75. }
  76. private void Initialize (ConstructorInfo con, object [] constructorArgs,
  77. PropertyInfo [] namedProperties, object [] propertyValues,
  78. FieldInfo [] namedFields, object [] fieldValues)
  79. {
  80. ctor = con;
  81. if (con == null)
  82. throw new ArgumentNullException ("con");
  83. if (constructorArgs == null)
  84. throw new ArgumentNullException ("constructorArgs");
  85. if (namedProperties == null)
  86. throw new ArgumentNullException ("namedProperties");
  87. if (propertyValues == null)
  88. throw new ArgumentNullException ("propertyValues");
  89. if (namedFields == null)
  90. throw new ArgumentNullException ("namedFields");
  91. if (fieldValues == null)
  92. throw new ArgumentNullException ("fieldValues");
  93. if (con.GetParameterCount () != constructorArgs.Length)
  94. throw new ArgumentException ("Parameter count does not match " +
  95. "passed in argument value count.");
  96. if (namedProperties.Length != propertyValues.Length)
  97. throw new ArgumentException ("Array lengths must be the same.",
  98. "namedProperties, propertyValues");
  99. if (namedFields.Length != fieldValues.Length)
  100. throw new ArgumentException ("Array lengths must be the same.",
  101. "namedFields, fieldValues");
  102. if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static ||
  103. (con.Attributes & MethodAttributes.Private) == MethodAttributes.Private)
  104. throw new ArgumentException ("Cannot have private or static constructor.");
  105. Type atype = ctor.DeclaringType;
  106. int i;
  107. i = 0;
  108. foreach (FieldInfo fi in namedFields) {
  109. Type t = fi.DeclaringType;
  110. if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
  111. throw new ArgumentException ("Field '" + fi.Name + "' does not belong to the same class as the constructor");
  112. // FIXME: Check enums and TypeBuilders as well
  113. if (fieldValues [i] != null)
  114. // IsEnum does not seem to work on TypeBuilders
  115. if (!(fi.FieldType is TypeBuilder) && !fi.FieldType.IsEnum && !fi.FieldType.IsAssignableFrom (fieldValues [i].GetType ())) {
  116. //
  117. // mcs allways uses object[] for array types and
  118. // MS.NET allows this
  119. //
  120. if (!fi.FieldType.IsArray)
  121. throw new ArgumentException ("Value of field '" + fi.Name + "' does not match field type: " + fi.FieldType);
  122. }
  123. i ++;
  124. }
  125. i = 0;
  126. foreach (PropertyInfo pi in namedProperties) {
  127. if (!pi.CanWrite)
  128. throw new ArgumentException ("Property '" + pi.Name + "' does not have a setter.");
  129. Type t = pi.DeclaringType;
  130. if ((atype != t) && (!t.IsSubclassOf (atype)) && (!atype.IsSubclassOf (t)))
  131. throw new ArgumentException ("Property '" + pi.Name + "' does not belong to the same class as the constructor");
  132. if (propertyValues [i] != null) {
  133. if (!(pi.PropertyType is TypeBuilder) && !pi.PropertyType.IsEnum && !pi.PropertyType.IsAssignableFrom (propertyValues [i].GetType ()))
  134. if (!pi.PropertyType.IsArray)
  135. throw new ArgumentException ("Value of property '" + pi.Name + "' does not match property type: " + pi.PropertyType + " -> " + propertyValues [i]);
  136. }
  137. i ++;
  138. }
  139. i = 0;
  140. foreach (ParameterInfo pi in con.GetParameters ()) {
  141. if (pi != null) {
  142. Type paramType = pi.ParameterType;
  143. if (constructorArgs [i] != null)
  144. if (!(paramType is TypeBuilder) && !paramType.IsEnum && !paramType.IsAssignableFrom (constructorArgs [i].GetType ()))
  145. if (!paramType.IsArray)
  146. throw new ArgumentException ("Value of argument " + i + " does not match parameter type: " + paramType + " -> " + constructorArgs [i]);
  147. }
  148. i ++;
  149. }
  150. data = GetBlob (atype.Assembly, con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues);
  151. }
  152. /* helper methods */
  153. internal static int decode_len (byte[] data, int pos, out int rpos) {
  154. int len = 0;
  155. if ((data [pos] & 0x80) == 0) {
  156. len = (int)(data [pos++] & 0x7f);
  157. } else if ((data [pos] & 0x40) == 0) {
  158. len = ((data [pos] & 0x3f) << 8) + data [pos + 1];
  159. pos += 2;
  160. } else {
  161. len = ((data [pos] & 0x1f) << 24) + (data [pos + 1] << 16) + (data [pos + 2] << 8) + data [pos + 3];
  162. pos += 4;
  163. }
  164. rpos = pos;
  165. return len;
  166. }
  167. internal static string string_from_bytes (byte[] data, int pos, int len)
  168. {
  169. return System.Text.Encoding.UTF8.GetString(data, pos, len);
  170. }
  171. internal string string_arg ()
  172. {
  173. int pos = 2;
  174. int len = decode_len (data, pos, out pos);
  175. return string_from_bytes (data, pos, len);
  176. }
  177. internal static UnmanagedMarshal get_umarshal (CustomAttributeBuilder customBuilder, bool is_field) {
  178. byte[] data = customBuilder.Data;
  179. UnmanagedType subtype = UnmanagedType.I4;
  180. int sizeConst = 0;
  181. int value;
  182. int utype; /* the (stupid) ctor takes a short or an enum ... */
  183. utype = (int)data [2];
  184. utype |= ((int)data [3]) << 8;
  185. string first_type_name = customBuilder.Ctor.GetParameters()[0].ParameterType.FullName;
  186. int pos = 6;
  187. if (first_type_name == "System.Int16")
  188. pos = 4;
  189. int nnamed = (int)data [pos++];
  190. nnamed |= ((int)data [pos++]) << 8;
  191. for (int i = 0; i < nnamed; ++i) {
  192. int paramType; // What is this ?
  193. paramType = (int)data [pos++];
  194. paramType |= ((int)data [pos++]) << 8;
  195. int len = decode_len (data, pos, out pos);
  196. string named_name = string_from_bytes (data, pos, len);
  197. pos += len;
  198. switch (named_name) {
  199. case "ArraySubType":
  200. value = (int)data [pos++];
  201. value |= ((int)data [pos++]) << 8;
  202. value |= ((int)data [pos++]) << 16;
  203. value |= ((int)data [pos++]) << 24;
  204. subtype = (UnmanagedType)value;
  205. break;
  206. case "SizeConst":
  207. value = (int)data [pos++];
  208. value |= ((int)data [pos++]) << 8;
  209. value |= ((int)data [pos++]) << 16;
  210. value |= ((int)data [pos++]) << 24;
  211. sizeConst = value;
  212. break;
  213. default:
  214. break;
  215. }
  216. }
  217. switch ((UnmanagedType)utype) {
  218. case UnmanagedType.LPArray:
  219. return UnmanagedMarshal.DefineLPArray (subtype);
  220. case UnmanagedType.SafeArray:
  221. return UnmanagedMarshal.DefineSafeArray (subtype);
  222. case UnmanagedType.ByValArray:
  223. return UnmanagedMarshal.DefineByValArray (sizeConst);
  224. case UnmanagedType.ByValTStr:
  225. return UnmanagedMarshal.DefineByValTStr (sizeConst);
  226. default:
  227. return UnmanagedMarshal.DefineUnmanagedMarshal ((UnmanagedType)utype);
  228. }
  229. }
  230. }
  231. }