1 // System.Reflection.Binder
3 // Sean MacIsaac (macisaac@ximian.com)
4 // Paolo Molaro (lupus@ximian.com)
6 // (C) Ximian, Inc. 2001 - 2002
8 using System.Globalization;
10 namespace System.Reflection
13 public abstract class Binder
15 protected Binder () {}
17 public abstract FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture);
18 public abstract MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state);
19 public abstract object ChangeType (object value, Type type, CultureInfo culture);
20 public abstract void ReorderArgumentArray( ref object[] args, object state);
21 public abstract MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers);
22 public abstract PropertyInfo SelectProperty( BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers);
24 static Binder default_binder;
26 internal static Binder DefaultBinder {
28 if (null == default_binder)
30 lock (typeof (Binder))
\r
32 if (default_binder == null)
33 default_binder = new Default ();
35 return default_binder;
39 return default_binder;
43 internal static bool ConvertArgs (Binder binder, object[] args, ParameterInfo[] pinfo, CultureInfo culture) {
45 if ( pinfo.Length == 0)
48 throw new TargetParameterCountException ();
50 if (pinfo.Length != args.Length)
51 throw new TargetParameterCountException ();
52 for (int i = 0; i < args.Length; ++i) {
53 object v = binder.ChangeType (args [i], pinfo[i].ParameterType, culture);
54 if ((v == null) && (args [i] != null))
61 internal sealed class Default : Binder {
62 public override FieldInfo BindToField (BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture)
65 throw new ArgumentNullException ("match");
66 foreach (FieldInfo f in match) {
67 if (check_type (value.GetType (), f.FieldType))
74 public override MethodBase BindToMethod (BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
78 types = Type.EmptyTypes;
80 types = new Type [args.Length];
81 for (int i = 0; i < args.Length; ++i) {
83 types [i] = args [i].GetType ();
86 MethodBase selected = SelectMethod (bindingAttr, match, types, modifiers);
91 static bool IsArrayAssignable (Type object_type, Type target_type)
93 if (object_type.IsArray && target_type.IsArray)
94 return IsArrayAssignable (object_type.GetElementType (), target_type.GetElementType ());
96 if (target_type.IsAssignableFrom (object_type))
102 public override object ChangeType (object value, Type type, CultureInfo culture)
106 Type vtype = value.GetType ();
107 if (vtype == type || type.IsAssignableFrom (vtype))
109 if (vtype.IsArray && type.IsArray){
110 if (IsArrayAssignable (vtype.GetElementType (), type.GetElementType ()))
114 if (check_type (vtype, type))
115 return Convert.ChangeType (value, type);
120 public override void ReorderArgumentArray (ref object[] args, object state)
122 //do nothing until we support named arguments
123 //throw new NotImplementedException ();
126 private static bool check_type (Type from, Type to) {
129 TypeCode fromt = Type.GetTypeCode (from);
130 TypeCode tot = Type.GetTypeCode (to);
135 case TypeCode.UInt16:
136 case TypeCode.UInt32:
138 case TypeCode.UInt64:
140 case TypeCode.Single:
141 case TypeCode.Double:
144 return to == typeof (object);
148 case TypeCode.UInt16:
150 case TypeCode.UInt32:
152 case TypeCode.UInt64:
154 case TypeCode.Single:
155 case TypeCode.Double:
158 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
164 case TypeCode.Single:
165 case TypeCode.Double:
168 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
169 case TypeCode.UInt16:
171 case TypeCode.UInt32:
173 case TypeCode.UInt64:
175 case TypeCode.Single:
176 case TypeCode.Double:
179 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
184 case TypeCode.Single:
185 case TypeCode.Double:
188 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
189 case TypeCode.UInt32:
191 case TypeCode.UInt64:
193 case TypeCode.Single:
194 case TypeCode.Double:
197 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
201 case TypeCode.Single:
202 case TypeCode.Double:
205 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
206 case TypeCode.UInt64:
209 case TypeCode.Single:
210 case TypeCode.Double:
213 return to == typeof (object) || (from.IsEnum && to == typeof (Enum));
214 case TypeCode.Single:
215 return tot == TypeCode.Double || to == typeof (object);
217 /* TODO: handle valuetype -> byref */
218 if (to == typeof (object) && from.IsValueType)
221 return to.IsAssignableFrom (from);
225 private static bool check_arguments (Type[] types, ParameterInfo[] args) {
226 for (int i = 0; i < types.Length; ++i) {
227 if (!check_type (types [i], args [i].ParameterType))
233 public override MethodBase SelectMethod (BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
238 throw new ArgumentNullException ("match");
239 /* first look for an exact match... */
240 for (i = 0; i < match.Length; ++i) {
242 ParameterInfo[] args = m.GetParameters ();
243 if (args.Length != types.Length)
245 for (j = 0; j < types.Length; ++j) {
246 if (types [j] != args [j].ParameterType)
249 if (j == types.Length)
252 for (i = 0; i < match.Length; ++i) {
254 ParameterInfo[] args = m.GetParameters ();
255 if (args.Length != types.Length)
257 if (!check_arguments (types, args))
264 public override PropertyInfo SelectProperty (BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers)
267 throw new ArgumentNullException ("match");
268 foreach (PropertyInfo m in match) {
269 ParameterInfo[] args = m.GetIndexParameters ();
270 if (args.Length != indexes.Length)
272 if (!check_arguments (indexes, args))