Binder.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // System.Reflection.Binder
  2. //
  3. // Sean MacIsaac ([email protected])
  4. // Paolo Molaro ([email protected])
  5. //
  6. // (C) Ximian, Inc. 2001 - 2002
  7. using System.Globalization;
  8. namespace System.Reflection
  9. {
  10. [Serializable]
  11. public abstract class Binder
  12. {
  13. protected Binder () {}
  14. public abstract FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture);
  15. public abstract MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state);
  16. public abstract object ChangeType (object value, Type type, CultureInfo culture);
  17. public abstract void ReorderArgumentArray( ref object[] args, object state);
  18. public abstract MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers);
  19. public abstract PropertyInfo SelectProperty( BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers);
  20. static Binder default_binder;
  21. internal static Binder DefaultBinder {
  22. get {
  23. lock (typeof (Binder)) {
  24. if (default_binder == null)
  25. default_binder = new Default ();
  26. return default_binder;
  27. }
  28. }
  29. }
  30. internal static bool ConvertArgs (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture) {
  31. if (args == null) {
  32. if ( pinfo.Length == 0)
  33. return true;
  34. else
  35. throw new TargetParameterCountException ();
  36. }
  37. if (pinfo.Length != args.Length)
  38. throw new TargetParameterCountException ();
  39. for (int i = 0; i < args.Length; ++i) {
  40. object v = binder.ChangeType (args [i], pinfo[i].ParameterType, culture);
  41. if ((v == null) && (args [i] != null))
  42. return false;
  43. args [i] = v;
  44. }
  45. return true;
  46. }
  47. internal sealed class Default : Binder {
  48. public override FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture)
  49. {
  50. if (match == null)
  51. throw new ArgumentNullException ("match");
  52. foreach (FieldInfo f in match) {
  53. if (check_type (value.GetType (), f.FieldType))
  54. return f;
  55. }
  56. return null;
  57. }
  58. [MonoTODO]
  59. public override MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
  60. {
  61. Type[] types;
  62. if (args == null)
  63. types = Type.EmptyTypes;
  64. else {
  65. types = new Type [args.Length];
  66. for (int i = 0; i < args.Length; ++i) {
  67. if (args [i] != null)
  68. types [i] = args [i].GetType ();
  69. }
  70. }
  71. MethodBase selected = SelectMethod (bindingAttr, match, types, modifiers);
  72. state = null;
  73. return selected;
  74. }
  75. public override object ChangeType (object value, Type type, CultureInfo culture)
  76. {
  77. if (value == null)
  78. return null;
  79. Type vtype = value.GetType ();
  80. if (vtype == type || type.IsAssignableFrom (vtype))
  81. return value;
  82. if (check_type (vtype, type))
  83. return Convert.ChangeType (value, type);
  84. return null;
  85. }
  86. [MonoTODO]
  87. public override void ReorderArgumentArray (ref object[] args, object state)
  88. {
  89. //do nothing until we support named arguments
  90. //throw new NotImplementedException ();
  91. }
  92. private static bool check_type (Type from, Type to) {
  93. if (from == to)
  94. return true;
  95. TypeCode fromt = Type.GetTypeCode (from);
  96. TypeCode tot = Type.GetTypeCode (to);
  97. switch (fromt) {
  98. case TypeCode.Char:
  99. switch (tot) {
  100. case TypeCode.UInt16:
  101. case TypeCode.UInt32:
  102. case TypeCode.Int32:
  103. case TypeCode.UInt64:
  104. case TypeCode.Int64:
  105. case TypeCode.Single:
  106. case TypeCode.Double:
  107. return true;
  108. }
  109. return false;
  110. case TypeCode.Byte:
  111. switch (tot) {
  112. case TypeCode.Char:
  113. case TypeCode.UInt16:
  114. case TypeCode.Int16:
  115. case TypeCode.UInt32:
  116. case TypeCode.Int32:
  117. case TypeCode.UInt64:
  118. case TypeCode.Int64:
  119. case TypeCode.Single:
  120. case TypeCode.Double:
  121. return true;
  122. }
  123. return false;
  124. case TypeCode.SByte:
  125. switch (tot) {
  126. case TypeCode.Int16:
  127. case TypeCode.Int32:
  128. case TypeCode.Int64:
  129. case TypeCode.Single:
  130. case TypeCode.Double:
  131. return true;
  132. }
  133. return false;
  134. case TypeCode.UInt16:
  135. switch (tot) {
  136. case TypeCode.UInt32:
  137. case TypeCode.Int32:
  138. case TypeCode.UInt64:
  139. case TypeCode.Int64:
  140. case TypeCode.Single:
  141. case TypeCode.Double:
  142. return true;
  143. }
  144. return false;
  145. case TypeCode.Int16:
  146. switch (tot) {
  147. case TypeCode.Int32:
  148. case TypeCode.Int64:
  149. case TypeCode.Single:
  150. case TypeCode.Double:
  151. return true;
  152. }
  153. return false;
  154. case TypeCode.UInt32:
  155. switch (tot) {
  156. case TypeCode.UInt64:
  157. case TypeCode.Int64:
  158. case TypeCode.Single:
  159. case TypeCode.Double:
  160. return true;
  161. }
  162. return false;
  163. case TypeCode.Int32:
  164. switch (tot) {
  165. case TypeCode.Int64:
  166. case TypeCode.Single:
  167. case TypeCode.Double:
  168. return true;
  169. }
  170. return false;
  171. case TypeCode.UInt64:
  172. case TypeCode.Int64:
  173. switch (tot) {
  174. case TypeCode.Single:
  175. case TypeCode.Double:
  176. return true;
  177. }
  178. return false;
  179. case TypeCode.Single:
  180. return tot == TypeCode.Double;
  181. default:
  182. /* TODO: handle valuetype -> byref */
  183. return to.IsAssignableFrom (from);
  184. }
  185. }
  186. private static bool check_arguments (Type[] types, ParameterInfo[] args) {
  187. for (int i = 0; i < types.Length; ++i) {
  188. if (!check_type (types [i], args [i].ParameterType))
  189. return false;
  190. }
  191. return true;
  192. }
  193. public override MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
  194. {
  195. MethodBase m;
  196. int i, j;
  197. if (match == null)
  198. throw new ArgumentNullException ("match");
  199. /* first look for an exact match... */
  200. for (i = 0; i < match.Length; ++i) {
  201. m = match [i];
  202. ParameterInfo[] args = m.GetParameters ();
  203. if (args.Length != types.Length)
  204. continue;
  205. for (j = 0; j < types.Length; ++j) {
  206. if (types [j] != args [j].ParameterType)
  207. break;
  208. }
  209. if (j == types.Length)
  210. return m;
  211. }
  212. for (i = 0; i < match.Length; ++i) {
  213. m = match [i];
  214. ParameterInfo[] args = m.GetParameters ();
  215. if (args.Length != types.Length)
  216. continue;
  217. if (!check_arguments (types, args))
  218. continue;
  219. return m;
  220. }
  221. return null;
  222. }
  223. public override PropertyInfo SelectProperty (BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers)
  224. {
  225. if (match == null)
  226. throw new ArgumentNullException ("match");
  227. foreach (PropertyInfo m in match) {
  228. ParameterInfo[] args = m.GetIndexParameters ();
  229. if (args.Length != indexes.Length)
  230. continue;
  231. if (!check_arguments (indexes, args))
  232. continue;
  233. return m;
  234. }
  235. return null;
  236. }
  237. }
  238. }
  239. }