Binder Class
[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]
Selects a member from a list of candidates, and performs type conversion from actual argument type to formal argument type.
Assembly: mscorlib (in mscorlib.dll)
The Binder type exposes the following members.
| Name | Description | |
|---|---|---|
![]() | BindToField | Selects a field from the given set of fields, based on the specified criteria. |
![]() | BindToMethod | Selects a method to invoke from the given set of methods, based on the supplied arguments. |
![]() | ChangeType | Changes the type of the given Object to the given Type. |
![]() | Equals(Object) | Determines whether the specified Object is equal to the current Object. (Inherited from Object.) |
![]() | Finalize | Allows an object to try to free resources and perform other cleanup operations before the Object is reclaimed by garbage collection. (Inherited from Object.) |
![]() | GetHashCode | Serves as a hash function for a particular type. (Inherited from Object.) |
![]() | GetType | Gets the Type of the current instance. (Inherited from Object.) |
![]() | MemberwiseClone | Creates a shallow copy of the current Object. (Inherited from Object.) |
![]() | ReorderArgumentArray | Upon returning from BindToMethod, restores the args argument to what it was when it came from BindToMethod. |
![]() | SelectMethod | Selects a method from the given set of methods, based on the argument type. |
![]() | SelectProperty | Selects a property from the given set of properties, based on the specified criteria. |
![]() | ToString | Returns a string that represents the current object. (Inherited from Object.) |
Implementations of the Binder class are used by methods such as Type.InvokeMember, which selects from a set of possible members to execute, based on a set of parameter types and argument values; Type.GetMethod, which selects a method based on parameter types; and so on.
A default implementation of the Binder class is provided by the Type.DefaultBinder property.
Notes to InheritorsWhen you inherit from Binder, you must override the following members: BindToMethod, BindToField, ReorderArgumentArray, SelectMethod, SelectProperty, and ChangeType.
The following example implements and demonstrates all members of the Binder class. The private method CanConvertFrom finds compatible types for a given type.
Note: |
|---|
To run this example, see Building examples that have static TextBlock controls for Windows Phone 8. |
using System; using System.Reflection; using System.Globalization; public class MyBinder : Binder { public MyBinder() : base() { } private class BinderState { public object[] args; } public override FieldInfo BindToField( BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture ) { if (match == null) throw new ArgumentNullException("match"); // Get a field for which the value parameter can be converted to the specified field type. for (int i = 0; i < match.Length; i++) if (ChangeType(value, match[i].FieldType, culture) != null) return match[i]; return null; } public override MethodBase BindToMethod( BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state ) { // Store the arguments to the method in a state object. BinderState myBinderState = new BinderState(); object[] arguments = new Object[args.Length]; args.CopyTo(arguments, 0); myBinderState.args = arguments; state = myBinderState; if (match == null) throw new ArgumentNullException(); // Find a method that has the same parameters as those of the args parameter. for (int i = 0; i < match.Length; i++) { // Count the number of parameters that match. int count = 0; ParameterInfo[] parameters = match[i].GetParameters(); // Go on to the next method if the number of parameters do not match. if (args.Length != parameters.Length) continue; // Match each of the parameters that the user expects the method to have. for (int j = 0; j < args.Length; j++) { // If the names parameter is not null, then reorder args. if (names != null) { if (names.Length != args.Length) throw new ArgumentException("names and args must have the same number of elements."); for (int k = 0; k < names.Length; k++) if (String.Compare(parameters[j].Name, names[k].ToString()) == 0) args[j] = myBinderState.args[k]; } // Determine whether the types specified by the user can be converted to the parameter type. if (ChangeType(args[j], parameters[j].ParameterType, culture) != null) count += 1; else break; } // Determine whether the method has been found. if (count == args.Length) return match[i]; } return null; } public override object ChangeType( object value, Type myChangeType, CultureInfo culture ) { // Determine whether the value parameter can be converted to a value of type myType. if (CanConvertFrom(value.GetType(), myChangeType)) // Return the converted object. return Convert.ChangeType(value, myChangeType, culture); else // Return null. return null; } public override void ReorderArgumentArray( ref object[] args, object state ) { // Return the args that had been reordered by BindToMethod. ((BinderState)state).args.CopyTo(args, 0); } public override MethodBase SelectMethod( BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers ) { if (match == null) throw new ArgumentNullException("match"); for (int i = 0; i < match.Length; i++) { // Count the number of parameters that match. int count = 0; ParameterInfo[] parameters = match[i].GetParameters(); // Go on to the next method if the number of parameters do not match. if (types.Length != parameters.Length) continue; // Match each of the parameters that the user expects the method to have. for (int j = 0; j < types.Length; j++) // Determine whether the types specified by the user can be converted to parameter type. if (CanConvertFrom(types[j], parameters[j].ParameterType)) count += 1; else break; // Determine whether the method has been found. if (count == types.Length) return match[i]; } return null; } public override PropertyInfo SelectProperty( BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers ) { if (match == null) throw new ArgumentNullException("match"); for (int i = 0; i < match.Length; i++) { // Count the number of indexes that match. int count = 0; ParameterInfo[] parameters = match[i].GetIndexParameters(); // Go on to the next property if the number of indexes do not match. if (indexes.Length != parameters.Length) continue; // Match each of the indexes that the user expects the property to have. for (int j = 0; j < indexes.Length; j++) // Determine whether the types specified by the user can be converted to index type. if (CanConvertFrom(indexes[j], parameters[j].ParameterType)) count += 1; else break; // Determine whether the property has been found. if (count == indexes.Length) // Determine whether the return type can be converted to the properties type. if (CanConvertFrom(returnType, match[i].PropertyType)) return match[i]; else continue; } return null; } // Determines whether type1 can be converted to type2. Check only for primitive types. private bool CanConvertFrom(Type type1, Type type2) { if (type1.IsPrimitive && type2.IsPrimitive) { TypeCode typeCode1 = Type.GetTypeCode(type1); TypeCode typeCode2 = Type.GetTypeCode(type2); // If both type1 and type2 have the same type, return true. if (typeCode1 == typeCode2) return true; // Possible conversions from Char follow. if (typeCode1 == TypeCode.Char) switch (typeCode2) { case TypeCode.UInt16: return true; case TypeCode.UInt32: return true; case TypeCode.Int32: return true; case TypeCode.UInt64: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from Byte follow. if (typeCode1 == TypeCode.Byte) switch (typeCode2) { case TypeCode.Char: return true; case TypeCode.UInt16: return true; case TypeCode.Int16: return true; case TypeCode.UInt32: return true; case TypeCode.Int32: return true; case TypeCode.UInt64: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from SByte follow. if (typeCode1 == TypeCode.SByte) switch (typeCode2) { case TypeCode.Int16: return true; case TypeCode.Int32: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from UInt16 follow. if (typeCode1 == TypeCode.UInt16) switch (typeCode2) { case TypeCode.UInt32: return true; case TypeCode.Int32: return true; case TypeCode.UInt64: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from Int16 follow. if (typeCode1 == TypeCode.Int16) switch (typeCode2) { case TypeCode.Int32: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from UInt32 follow. if (typeCode1 == TypeCode.UInt32) switch (typeCode2) { case TypeCode.UInt64: return true; case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from Int32 follow. if (typeCode1 == TypeCode.Int32) switch (typeCode2) { case TypeCode.Int64: return true; case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from UInt64 follow. if (typeCode1 == TypeCode.UInt64) switch (typeCode2) { case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from Int64 follow. if (typeCode1 == TypeCode.Int64) switch (typeCode2) { case TypeCode.Single: return true; case TypeCode.Double: return true; default: return false; } // Possible conversions from Single follow. if (typeCode1 == TypeCode.Single) switch (typeCode2) { case TypeCode.Double: return true; default: return false; } } return false; } } public class Example { public short myFieldB; public int myFieldA; private static System.Windows.Controls.TextBlock outputBlock; public void MyMethod(long i, char k) { outputBlock.Text += String.Format("This is MyMethod(long i, char k)\n"); } public void MyMethod(long i, long j) { outputBlock.Text += String.Format("This is MyMethod(long i, long j)\n"); } public static void Demo(System.Windows.Controls.TextBlock outputBlock) { Example.outputBlock = outputBlock; // Get the type of Example. Type myType = typeof(Example); // Get the instance of Example. object myInstance = new Example(); outputBlock.Text += "Displaying the results of using the MyBinder binder.\n"; // Get the method information for MyMethod. MethodInfo myMethod = myType.GetMethod("MyMethod", BindingFlags.Public | BindingFlags.Instance, new MyBinder(), new Type[] { typeof(short), typeof(short) }, null); outputBlock.Text += myMethod.ToString() + "\n"; // Invoke MyMethod. myType.InvokeMember("MyMethod", BindingFlags.InvokeMethod, new MyBinder(), myInstance, new Object[] { (int)32, (int)32 }); } } /* This code produces the following output: Displaying the results of using the MyBinder binder. Void MyMethod(Int64, Int64) This is MyMethod(long i, long j). */


Note: