⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplebinder.cs

📁 Microsoft.NET.框架程序设计修订版中的书中源码
💻 CS
📖 第 1 页 / 共 2 页
字号:
            candidates.Add(m);
      }

      // If no exact match was found and the caller wants an exact match, throw
      Int32 numTests = ((BindingFlags.ExactBinding & bindingAttr) != 0) ? 1 : 3;

      for (Int32 test = 0; test < numTests; test++) {
         CompareParamAndArgTypesFlags flags = CompareParamAndArgTypesFlags.Exact;
         
         // Look for methods whose parameter types exactly match the argument types
         if (test == 0) 
            flags = CompareParamAndArgTypesFlags.Exact;

         // Look for methods that can accomodate the parameters passed.
         if (test == 1) 
            flags = CompareParamAndArgTypesFlags.AllowBaseTypes;
         
         // Check whether any conversion could be applied on primitives as well. 
         // NOTE: We bind to the first matching method; not the best matching method.
         // Look for methods that can accomodate the parameters passed.
         if (test == 2) 
            flags = CompareParamAndArgTypesFlags.AllowBaseTypes | 
               CompareParamAndArgTypesFlags.CoerceValueTypes;

         // Assume that no method matches the argument's parameters
         MethodBase match = null;

         // Check ALL of the methods
         foreach (MethodBase m in candidates) {

            if (CompareParamAndArgTypes(m.GetParameters(), argTypes, flags)) {
               // A matching method was found

               // If we found a matching method previously, then we don't know
               // how to select one of them.
               if (match != null) {
                  // Note, when doing an exact match this can occur if multiple 
                  // methods differ only by return type
                  throw new AmbiguousMatchException("Multiple methods match the specified parameter types.");
               }

               // Save the matching method
               match = m;
            }
         }

         // One matching method was found, return it
         if (match != null) return match;
      }

      // No matching method was found, throw
      throw new MissingMethodException("Member not found.");
   }

   
   // Called to return the parameters of a property
   private static ParameterInfo[] GetPropertyParams(PropertyInfo p) {

      // If a get accessor method exists, return its parameters
      MethodInfo m = p.GetGetMethod();
      if (m != null) return m.GetParameters();

      // No get accessor method exists, use the set access method
      m = p.GetSetMethod();
      ParameterInfo[] setParams = m.GetParameters();

      // Copy all elements but the last (the property's type) to a new array
      ParameterInfo[] paramTypes = new ParameterInfo[setParams.Length - 1];
      Array.Copy(setParams, paramTypes, paramTypes.Length);

      // Return the copy
      return paramTypes;
   }


   // GetProperty calls this method to select a specific property. 
   // This code performs uses simple conversion rules to bind.
   public override PropertyInfo SelectProperty(
      BindingFlags bindingAttr,        // Flags to restrict options
      PropertyInfo[] properties,       // Property subset selected by reflection
      Type returnType,                 // Property's return type
      Type[] argTypes,                 // Set of argument types
      ParameterModifier[] modifiers) { // Modifiers (usually ignored)
      
      // This ArrayList contains the set of possible properties
      ArrayList candidates = new ArrayList();

      // Build the set of candidate properties removing any property that 
      // doesn't have the specified number of arguments.

      // Only consider properties that have the same number of arguments and type
      Int32 argCount = (argTypes == null) ? 0 : argTypes.Length;
      foreach (PropertyInfo p in properties) {
         if (GetPropertyParams(p).Length == argCount)
            // Check the property's type
            if ((returnType == null) || (returnType == p.PropertyType))
               candidates.Add(p);
      }

      // If no exact match was found and the caller wants an exact match, throw
      Int32 numTests = ((BindingFlags.ExactBinding & bindingAttr) != 0) ? 1 : 3;

      for (Int32 test = 0; test < numTests; test++) {
         CompareParamAndArgTypesFlags flags = CompareParamAndArgTypesFlags.Exact;
         
         // Look for properties whose parameter types exactly match the argument types
         if (test == 0) 
            flags = CompareParamAndArgTypesFlags.Exact;

         // Look for properties that can accomodate the parameters passed.
         if (test == 1) 
            flags = CompareParamAndArgTypesFlags.AllowBaseTypes;
         
         // Check whether any conversion could be applied on primitives as well. 
         // NOTE: We bind to the first matching property; not the best matching property.
         // Look for properties that can accomodate the parameters passed.
         if (test == 2) 
            flags = CompareParamAndArgTypesFlags.AllowBaseTypes | 
               CompareParamAndArgTypesFlags.CoerceValueTypes;

         // Assume that no property matches the argument's parameters
         PropertyInfo match = null;

         // Check ALL of the properties
         foreach (PropertyInfo p in candidates) {

            if (CompareParamAndArgTypes(GetPropertyParams(p), argTypes, flags)) {
               // A matching property was found

               // If we found a matching property previously, then we don't know
               // how to select one of them.
               if (match != null) {
                  // Note, when doing an exact match this can occur if multiple 
                  // properties differ only by type
                  throw new AmbiguousMatchException("Multiple properties match the specified parameter types.");
               }

               // Save the matching property
               match = p;
            }
         }

         // One matching property was found, return it
         if (match != null) return match;
      }

      // No matching property was found, throw
      throw new MissingMemberException("Member not found.");
   }
   
 	
///////////////////////////////////////////////////////////////////////////////


   // This table indicates what conversions this binder allows
   static readonly TypeCode[][] AllowedConversions = new TypeCode[19][];

   // This static constructor initializes the conversion table
   static SimpleBinder() {
      // For example, Char can be convert to SByte, Byte, or UInt16
      AllowedConversions[(Int32) TypeCode.Char]   = new TypeCode[] 
         { TypeCode.SByte, TypeCode.Byte, TypeCode.UInt16 };

      AllowedConversions[(Int32) TypeCode.Int16]  = new TypeCode[] 
         { TypeCode.SByte, TypeCode.Byte };

      AllowedConversions[(Int32) TypeCode.UInt16] = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte };

      AllowedConversions[(Int32) TypeCode.Int32]  = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16 };

      AllowedConversions[(Int32) TypeCode.UInt32] = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16 };

      AllowedConversions[(Int32) TypeCode.Int64]  = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32 };
      
      AllowedConversions[(Int32) TypeCode.UInt64] = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32 };
      
      AllowedConversions[(Int32) TypeCode.Single] = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16 };
      
      AllowedConversions[(Int32) TypeCode.Double] = new TypeCode[] 
         { TypeCode.Char,  TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16, TypeCode.Int32, TypeCode.UInt32, TypeCode.Single };
   }


   // Returns 'true' if the binder can convert from fromType to toType
   private static Boolean CanConvertPrimitiveType(Type fromType, Type toType) {
      // If the types are the same, of course we can convert
      if (fromType == toType) return true;

      // Check table to see if fromType can be converted to anything
      TypeCode fromTypeCode = Type.GetTypeCode(fromType);
      if (AllowedConversions[(Int32) fromTypeCode] == null) 
         return false;

      // Check table to see if conversion from fromType to toType is allowed
      TypeCode toTypeCode = Type.GetTypeCode(toType);
      if (Array.IndexOf(AllowedConversions[(Int32) toTypeCode], fromTypeCode) != -1)
         return true;

      // Conversion is not allowed
      return false;
   }


   // Returns new object converted from original type
   private static Object DoConvertPrimitiveType(Object value, Type toType) {
      // If conversion isn't allowed, throw
      if (!CanConvertPrimitiveType(value.GetType(), toType))
         throw new InvalidCastException();

      // Conversion is allowed, convert and return the new object
      return Convert.ChangeType(value, toType);
   }
}


//////////////////////////////// End of File //////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -