DefaultBinder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / DefaultBinder.cs / 1305376 / DefaultBinder.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// 
// 
// This class represents the Default COM+ binder.
// 
//
namespace System {

    using System; 
    using System.Reflection;
    using System.Runtime.CompilerServices; 
    using System.Runtime.Versioning; 
    using System.Diagnostics.Contracts;
    using CultureInfo = System.Globalization.CultureInfo; 
    //Marked serializable even though it has no state.
    [Serializable]
    internal class DefaultBinder : Binder
    { 
        // This method is passed a set of methods and must choose the best
        // fit.  The methods all have the same number of arguments and the object 
        // array args.  On exit, this method will choice the best fit method 
        // and coerce the args to match that method.  By match, we mean all primitive
        // arguments are exact matchs and all object arguments are exact or subclasses 
        // of the target.  If the target OR is an interface, the object must implement
        // that interface.  There are a couple of exceptions
        // thrown when a method cannot be returned.  If no method matchs the args and
        // ArgumentException is thrown.  If multiple methods match the args then 
        // an AmbiguousMatchException is thrown.
        // 
        // The most specific match will be selected. 
        //
        [System.Security.SecuritySafeCritical]  // auto-generated 
        public override MethodBase BindToMethod(
            BindingFlags bindingAttr, MethodBase[] match, ref Object[] args,
            ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, out Object state)
        { 
            if (match == null || match.Length == 0)
                throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match"); 
            Contract.EndContractBlock(); 

            MethodBase[] candidates = (MethodBase[]) match.Clone(); 

            int i;
            int j;
 
            state = null;
 
            #region Map named parameters to candidate parameter postions 
            // We are creating an paramOrder array to act as a mapping
            //  between the order of the args and the actual order of the 
            //  parameters in the method.  This order may differ because
            //  named parameters (names) may change the order.  If names
            //  is not provided, then we assume the default mapping (0,1,...)
            int[][] paramOrder = new int[candidates.Length][]; 

            for (i = 0; i < candidates.Length; i++) 
            { 
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();
 
                // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted
                paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length];

                if (names == null) 
                {
                    // Default mapping 
                    for (j = 0; j < args.Length; j++) 
                        paramOrder[i][j] = j;
                } 
                else
                {
                    // Named parameters, reorder the mapping.  If CreateParamOrder fails, it means that the method
                    // doesn't have a name that matchs one of the named parameters so we don't consider it any further. 
                     if (!CreateParamOrder(paramOrder[i], par, names))
                         candidates[i] = null; 
                } 
            }
            #endregion 

            Type[] paramArrayTypes = new Type[candidates.Length];

            Type[] argTypes = new Type[args.Length]; 

            #region Cache the type of the provided arguments 
            // object that contain a null are treated as if they were typeless (but match either object 
            // references or value classes).  We mark this condition by placing a null in the argTypes array.
            for (i = 0; i < args.Length; i++) 
            {
                if (args[i] != null)
                {
                    argTypes[i] = args[i].GetType(); 
                }
            } 
            #endregion 

 
            // Find the method that matches...
            int CurIdx = 0;
            bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0);
 
            Type paramArrayType = null;
 
            #region Filter methods by parameter count and type 
            for (i = 0; i < candidates.Length; i++)
            { 
                paramArrayType = null;

                // If we have named parameters then we may have a hole in the candidates array.
                if (candidates[i] == null) 
                    continue;
 
                // Validate the parameters. 
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();
 
                #region Match method by parameter count
                if (par.Length == 0)
                {
                    #region No formal parameters 
                    if (args.Length != 0)
                    { 
                        if ((candidates[i].CallingConvention & CallingConventions.VarArgs) == 0) 
                            continue;
                    } 

                    // This is a valid routine so we move it up the candidates list.
                    paramOrder[CurIdx] = paramOrder[i];
                    candidates[CurIdx++] = candidates[i]; 

                    continue; 
                    #endregion 
                }
                else if (par.Length > args.Length) 
                {
                    #region Shortage of provided parameters
                    // If the number of parameters is greater than the number of args then
                    // we are in the situation were we may be using default values. 
                    for (j = args.Length; j < par.Length - 1; j++)
                    { 
                        if (par[j].DefaultValue == System.DBNull.Value) 
                           break;
                    } 

                    if (j != par.Length - 1)
                        continue;
 
                    if (par[j].DefaultValue == System.DBNull.Value)
                    { 
                        if (!par[j].ParameterType.IsArray) 
                            continue;
 
                        if (!par[j].IsDefined(typeof(ParamArrayAttribute), true))
                            continue;

                        paramArrayType = par[j].ParameterType.GetElementType(); 
                    }
                    #endregion 
                } 
                else if (par.Length < args.Length)
                { 
                    #region Excess provided parameters
                    // test for the ParamArray case
                    int lastArgPos = par.Length - 1;
 
                    if (!par[lastArgPos].ParameterType.IsArray)
                        continue; 
 
                    if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true))
                        continue; 

                    if (paramOrder[i][lastArgPos] != lastArgPos)
                        continue;
 
                    paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    #endregion 
                } 
                else
                { 
                    #region Test for paramArray, save paramArray type
                    int lastArgPos = par.Length - 1;

                    if (par[lastArgPos].ParameterType.IsArray 
                        && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)
                        && paramOrder[i][lastArgPos] == lastArgPos) 
                    { 
                        if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos]))
                            paramArrayType = par[lastArgPos].ParameterType.GetElementType(); 
                    }
                    #endregion
                }
                #endregion 

                Type pCls = null; 
                int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length; 

                #region Match method by parameter type 
                for (j = 0; j < argsToCheck; j++)
                {
                    #region Classic argument coersion checks
                    // get the formal type 
                    pCls = par[j].ParameterType;
 
                    if (pCls.IsByRef) 
                        pCls = pCls.GetElementType();
 
                    // the type is the same
                    if (pCls == argTypes[paramOrder[i][j]])
                        continue;
 
                    // a default value is available
                    if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing) 
                        continue; 

                    // the argument was null, so it matches with everything 
                    if (args[paramOrder[i][j]] == null)
                        continue;

                    // the type is Object, so it will match everything 
                    if (pCls == typeof(Object))
                        continue; 
 
                    // now do a "classic" type check
                    if (pCls.IsPrimitive) 
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)pCls))
                        {
#if !FEATURE_COMINTEROP 
                            if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo))
                                continue; 
#endif 
                            break;
                        } 
                    }
                    else
                    {
                        if (argTypes[paramOrder[i][j]] == null) 
                            continue;
 
                        if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]])) 
                        {
                            if (argTypes[paramOrder[i][j]].IsCOMObject) 
                            {
                                if (pCls.IsInstanceOfType(args[paramOrder[i][j]]))
                                    continue;
                            } 
#if !FEATURE_COMINTEROP
                            if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) 
                                continue; 
#endif
                            break; 
                        }
                    }
                    #endregion
                } 

                if (paramArrayType != null && j == par.Length - 1) 
                { 
                    #region Check that excess arguments can be placed in the param array
                    for (; j < args.Length; j++) 
                    {
                        if (paramArrayType.IsPrimitive)
                        {
                            if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], (RuntimeType)paramArrayType)) 
                                break;
                        } 
                        else 
                        {
                            if (argTypes[j] == null) 
                                continue;

                            if (!paramArrayType.IsAssignableFrom(argTypes[j]))
                            { 
                                if (argTypes[j].IsCOMObject)
                                { 
                                    if (paramArrayType.IsInstanceOfType(args[j])) 
                                        continue;
                                } 

                                break;
                            }
                        } 
                    }
                    #endregion 
                } 
                #endregion
 
                if (j == args.Length)
                {
                    #region This is a valid routine so we move it up the candidates list
                    paramOrder[CurIdx] = paramOrder[i]; 
                    paramArrayTypes[CurIdx] = paramArrayType;
                    candidates[CurIdx++] = candidates[i]; 
                    #endregion 
                }
            } 
            #endregion

            // If we didn't find a method
            if (CurIdx == 0) 
                throw new MissingMethodException(Environment.GetResourceString("MissingMember"));
 
            if (CurIdx == 1) 
            {
                #region Found only one method 
                if (names != null)
                {
                    state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null);
                    ReorderParams(paramOrder[0],args); 
                }
 
                // If the parameters and the args are not the same length or there is a paramArray 
                //  then we need to create a argument array.
                ParameterInfo[] parms = candidates[0].GetParametersNoCopy(); 

                if (parms.Length == args.Length)
                {
                    if (paramArrayTypes[0] != null) 
                    {
                        Object[] objs = new Object[parms.Length]; 
                        int lastPos = parms.Length - 1; 
                        Array.Copy(args, 0, objs, 0, lastPos);
                        objs[lastPos] = Array.UnsafeCreateInstance(paramArrayTypes[0], 1); 
                        ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                        args = objs;
                    }
                } 
                else if (parms.Length > args.Length)
                { 
                    Object[] objs = new Object[parms.Length]; 

                    for (i=0;i args.Length)
            { 
                Object[] objs = new Object[parameters.Length];
 
                for (i=0;i binderState.m_originalSize) {
                    Object[] newArgs = new Object[binderState.m_originalSize]; 
                    Array.Copy(args, 0, newArgs, 0, binderState.m_originalSize);
                    args = newArgs;
                }
            } 
        }
 
        // Return any exact bindings that may exist. (This method is not defined on the 
        //  Binder and is used by RuntimeType.)
        public static MethodBase ExactBinding(MethodBase[] match,Type[] types,ParameterModifier[] modifiers) 
        {
            if (match==null)
                throw new ArgumentNullException("match");
            Contract.EndContractBlock(); 
            MethodBase[] aExactMatches = new MethodBase[match.Length];
            int cExactMatches = 0; 
 
            for (int i=0;i= p.Length - 1 is being put in the param array 

                if (paramArrayType1 != null && paramOrder1[i] >= p1.Length - 1)
                    c1 = paramArrayType1;
                else 
                    c1 = p1[paramOrder1[i]].ParameterType;
 
                if (paramArrayType2 != null && paramOrder2[i] >= p2.Length - 1) 
                    c2 = paramArrayType2;
                else 
                    c2 = p2[paramOrder2[i]].ParameterType;

                if (c1 == c2) continue;
 
                switch (FindMostSpecificType(c1, c2, types[i])) {
                    case 0: return 0; 
                    case 1: p1Less = true; break; 
                    case 2: p2Less = true; break;
                } 
            }

            // Two way p1Less and p2Less can be equal.  All the arguments are the
            //  same they both equal false, otherwise there were things that both 
            //  were the most specific type on....
            if (p1Less == p2Less) 
            { 
                // if we cannot tell which is a better match based on parameter types (p1Less == p2Less),
                // let's see which one has the most matches without using the params array (the longer one wins). 
                if (!p1Less && args != null)
                {
                    if (p1.Length > p2.Length)
                    { 
                        return 1;
                    } 
                    else if (p2.Length > p1.Length) 
                    {
                        return 2; 
                    }
                }

                return 0; 
            }
            else 
            { 
                return (p1Less == true) ? 1 : 2;
            } 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        private static int FindMostSpecificType(Type c1, Type c2, Type t) 
        {
            // If the two types are exact move on... 
            if (c1 == c2) 
                return 0;
 
            if (c1 == t)
                return 1;

            if (c2 == t) 
                return 2;
 
            bool c1FromC2; 
            bool c2FromC1;
 
            if (c1.IsByRef || c2.IsByRef)
            {
                if (c1.IsByRef && c2.IsByRef)
                { 
                    c1 = c1.GetElementType();
                    c2 = c2.GetElementType(); 
                } 
                else if (c1.IsByRef)
                { 
                    if (c1.GetElementType() == c2)
                        return 2;

                    c1 = c1.GetElementType(); 
                }
                else 
                { 
                    if (c2.GetElementType() == c1)
                        return 1; 

                    c2 = c2.GetElementType();
                }
            } 

 
            if (c1.IsPrimitive && c2.IsPrimitive) 
            {
                c1FromC2 = CanConvertPrimitive((RuntimeType)c2, (RuntimeType)c1); 
                c2FromC1 = CanConvertPrimitive((RuntimeType)c1, (RuntimeType)c2);
            }
            else
            { 
                c1FromC2 = c1.IsAssignableFrom(c2);
                c2FromC1 = c2.IsAssignableFrom(c1); 
            } 

            if (c1FromC2 == c2FromC1) 
                return 0;

            if (c1FromC2)
            { 
                return 2;
            } 
            else 
            {
                return 1; 
            }
        }

        private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type paramArrayType1, 
                                                  MethodBase m2, int[] paramOrder2, Type paramArrayType2,
                                                  Type[] types, Object[] args) 
        { 
            // Find the most specific method based on the parameters.
            int res = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1, 
                                       m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args);

            // If the match was not ambigous then return the result.
            if (res != 0) 
                return res;
 
            // Check to see if the methods have the exact same name and signature. 
            if (CompareMethodSigAndName(m1, m2))
            { 
                // Determine the depth of the declaring types for both methods.
                int hierarchyDepth1 = GetHierarchyDepth(m1.DeclaringType);
                int hierarchyDepth2 = GetHierarchyDepth(m2.DeclaringType);
 
                // The most derived method is the most specific one.
                if (hierarchyDepth1 == hierarchyDepth2) 
                { 
                    return 0;
                } 
                else if (hierarchyDepth1 < hierarchyDepth2)
                {
                    return 2;
                } 
                else
                { 
                    return 1; 
                }
            } 

            // The match is ambigous.
            return 0;
        } 

        private static int FindMostSpecificField(FieldInfo cur1,FieldInfo cur2) 
        { 
            // Check to see if the fields have the same name.
            if (cur1.Name == cur2.Name) 
            {
                int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType);
                int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType);
 
                if (hierarchyDepth1 == hierarchyDepth2) {
                    Contract.Assert(cur1.IsStatic != cur2.IsStatic, "hierarchyDepth1 == hierarchyDepth2"); 
                    return 0; 
                }
                else if (hierarchyDepth1 < hierarchyDepth2) 
                    return 2;
                else
                    return 1;
            } 

            // The match is ambigous. 
            return 0; 
        }
 
        private static int FindMostSpecificProperty(PropertyInfo cur1,PropertyInfo cur2)
        {
            // Check to see if the fields have the same name.
            if (cur1.Name == cur2.Name) 
            {
                int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType); 
                int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType); 

                if (hierarchyDepth1 == hierarchyDepth2) { 
                    return 0;
                }
                else if (hierarchyDepth1 < hierarchyDepth2)
                    return 2; 
                else
                    return 1; 
            } 

            // The match is ambigous. 
            return 0;
        }

        internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2) 
        {
            ParameterInfo[] params1 = m1.GetParametersNoCopy(); 
            ParameterInfo[] params2 = m2.GetParametersNoCopy(); 

            if (params1.Length != params2.Length) 
                return false;

            int numParams = params1.Length;
            for (int i = 0; i < numParams; i++) 
            {
                if (params1[i].ParameterType != params2[i].ParameterType) 
                    return false; 
            }
 
            return true;
        }

        internal static int GetHierarchyDepth(Type t) 
        {
            int depth = 0; 
 
            Type currentType = t;
            do 
            {
                depth++;
                currentType = currentType.BaseType;
            } while (currentType != null); 

            return depth; 
        } 

        internal static MethodBase FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches) 
        {
            int deepestHierarchy = 0;
            MethodBase methWithDeepestHierarchy = null;
 
            for (int i = 0; i < cMatches; i++)
            { 
                // Calculate the depth of the hierarchy of the declaring type of the 
                // current method.
                int currentHierarchyDepth = GetHierarchyDepth(match[i].DeclaringType); 

                // The two methods have the same name, signature, and hierarchy depth.
                // This can only happen if at least one is vararg or generic.
                if (currentHierarchyDepth == deepestHierarchy) 
                {
                    throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); 
                } 

                // Check to see if this method is on the most derived class. 
                if (currentHierarchyDepth > deepestHierarchy)
                {
                    deepestHierarchy = currentHierarchyDepth;
                    methWithDeepestHierarchy = match[i]; 
                }
            } 
 
            return methWithDeepestHierarchy;
        } 

        // CanConvertPrimitive
        // This will determine if the source can be converted to the target type
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool CanConvertPrimitive(RuntimeType source,RuntimeType target); 

        // CanConvertPrimitiveObjectToType 
        // This method will determine if the primitive object can be converted
        //  to a type.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        static internal extern bool CanConvertPrimitiveObjectToType(Object source,RuntimeType type); 
 
        // This method will sort the vars array into the mapping order stored
        //  in the paramOrder array. 
        private static void ReorderParams(int[] paramOrder,Object[] vars)
        {
            object[] varsCopy = new object[vars.Length];
            for (int i = 0; i < vars.Length; i ++) 
                varsCopy[i] = vars[i];
 
            for (int i = 0; i < vars.Length; i ++) 
                vars[i] = varsCopy[paramOrder[i]];
        } 

        // This method will create the mapping between the Parameters and the underlying
        //  data based upon the names array.  The names array is stored in the same order
        //  as the values and maps to the parameters of the method.  We store the mapping 
        //  from the parameters to the names in the paramOrder array.  All parameters that
        //  don't have matching names are then stored in the array in order. 
        private static bool CreateParamOrder(int[] paramOrder,ParameterInfo[] pars,String[] names) 
        {
            bool[] used = new bool[pars.Length]; 

            // Mark which parameters have not been found in the names list
            for (int i=0;i args.Length) ? par.Length : args.Length];

                if (names == null) 
                {
                    // Default mapping 
                    for (j = 0; j < args.Length; j++) 
                        paramOrder[i][j] = j;
                } 
                else
                {
                    // Named parameters, reorder the mapping.  If CreateParamOrder fails, it means that the method
                    // doesn't have a name that matchs one of the named parameters so we don't consider it any further. 
                     if (!CreateParamOrder(paramOrder[i], par, names))
                         candidates[i] = null; 
                } 
            }
            #endregion 

            Type[] paramArrayTypes = new Type[candidates.Length];

            Type[] argTypes = new Type[args.Length]; 

            #region Cache the type of the provided arguments 
            // object that contain a null are treated as if they were typeless (but match either object 
            // references or value classes).  We mark this condition by placing a null in the argTypes array.
            for (i = 0; i < args.Length; i++) 
            {
                if (args[i] != null)
                {
                    argTypes[i] = args[i].GetType(); 
                }
            } 
            #endregion 

 
            // Find the method that matches...
            int CurIdx = 0;
            bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0);
 
            Type paramArrayType = null;
 
            #region Filter methods by parameter count and type 
            for (i = 0; i < candidates.Length; i++)
            { 
                paramArrayType = null;

                // If we have named parameters then we may have a hole in the candidates array.
                if (candidates[i] == null) 
                    continue;
 
                // Validate the parameters. 
                ParameterInfo[] par = candidates[i].GetParametersNoCopy();
 
                #region Match method by parameter count
                if (par.Length == 0)
                {
                    #region No formal parameters 
                    if (args.Length != 0)
                    { 
                        if ((candidates[i].CallingConvention & CallingConventions.VarArgs) == 0) 
                            continue;
                    } 

                    // This is a valid routine so we move it up the candidates list.
                    paramOrder[CurIdx] = paramOrder[i];
                    candidates[CurIdx++] = candidates[i]; 

                    continue; 
                    #endregion 
                }
                else if (par.Length > args.Length) 
                {
                    #region Shortage of provided parameters
                    // If the number of parameters is greater than the number of args then
                    // we are in the situation were we may be using default values. 
                    for (j = args.Length; j < par.Length - 1; j++)
                    { 
                        if (par[j].DefaultValue == System.DBNull.Value) 
                           break;
                    } 

                    if (j != par.Length - 1)
                        continue;
 
                    if (par[j].DefaultValue == System.DBNull.Value)
                    { 
                        if (!par[j].ParameterType.IsArray) 
                            continue;
 
                        if (!par[j].IsDefined(typeof(ParamArrayAttribute), true))
                            continue;

                        paramArrayType = par[j].ParameterType.GetElementType(); 
                    }
                    #endregion 
                } 
                else if (par.Length < args.Length)
                { 
                    #region Excess provided parameters
                    // test for the ParamArray case
                    int lastArgPos = par.Length - 1;
 
                    if (!par[lastArgPos].ParameterType.IsArray)
                        continue; 
 
                    if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true))
                        continue; 

                    if (paramOrder[i][lastArgPos] != lastArgPos)
                        continue;
 
                    paramArrayType = par[lastArgPos].ParameterType.GetElementType();
                    #endregion 
                } 
                else
                { 
                    #region Test for paramArray, save paramArray type
                    int lastArgPos = par.Length - 1;

                    if (par[lastArgPos].ParameterType.IsArray 
                        && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)
                        && paramOrder[i][lastArgPos] == lastArgPos) 
                    { 
                        if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos]))
                            paramArrayType = par[lastArgPos].ParameterType.GetElementType(); 
                    }
                    #endregion
                }
                #endregion 

                Type pCls = null; 
                int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length; 

                #region Match method by parameter type 
                for (j = 0; j < argsToCheck; j++)
                {
                    #region Classic argument coersion checks
                    // get the formal type 
                    pCls = par[j].ParameterType;
 
                    if (pCls.IsByRef) 
                        pCls = pCls.GetElementType();
 
                    // the type is the same
                    if (pCls == argTypes[paramOrder[i][j]])
                        continue;
 
                    // a default value is available
                    if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing) 
                        continue; 

                    // the argument was null, so it matches with everything 
                    if (args[paramOrder[i][j]] == null)
                        continue;

                    // the type is Object, so it will match everything 
                    if (pCls == typeof(Object))
                        continue; 
 
                    // now do a "classic" type check
                    if (pCls.IsPrimitive) 
                    {
                        if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)pCls))
                        {
#if !FEATURE_COMINTEROP 
                            if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo))
                                continue; 
#endif 
                            break;
                        } 
                    }
                    else
                    {
                        if (argTypes[paramOrder[i][j]] == null) 
                            continue;
 
                        if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]])) 
                        {
                            if (argTypes[paramOrder[i][j]].IsCOMObject) 
                            {
                                if (pCls.IsInstanceOfType(args[paramOrder[i][j]]))
                                    continue;
                            } 
#if !FEATURE_COMINTEROP
                            if (CanChangeType(args[paramOrder[i][j]],pCls,cultureInfo)) 
                                continue; 
#endif
                            break; 
                        }
                    }
                    #endregion
                } 

                if (paramArrayType != null && j == par.Length - 1) 
                { 
                    #region Check that excess arguments can be placed in the param array
                    for (; j < args.Length; j++) 
                    {
                        if (paramArrayType.IsPrimitive)
                        {
                            if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], (RuntimeType)paramArrayType)) 
                                break;
                        } 
                        else 
                        {
                            if (argTypes[j] == null) 
                                continue;

                            if (!paramArrayType.IsAssignableFrom(argTypes[j]))
                            { 
                                if (argTypes[j].IsCOMObject)
                                { 
                                    if (paramArrayType.IsInstanceOfType(args[j])) 
                                        continue;
                                } 

                                break;
                            }
                        } 
                    }
                    #endregion 
                } 
                #endregion
 
                if (j == args.Length)
                {
                    #region This is a valid routine so we move it up the candidates list
                    paramOrder[CurIdx] = paramOrder[i]; 
                    paramArrayTypes[CurIdx] = paramArrayType;
                    candidates[CurIdx++] = candidates[i]; 
                    #endregion 
                }
            } 
            #endregion

            // If we didn't find a method
            if (CurIdx == 0) 
                throw new MissingMethodException(Environment.GetResourceString("MissingMember"));
 
            if (CurIdx == 1) 
            {
                #region Found only one method 
                if (names != null)
                {
                    state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null);
                    ReorderParams(paramOrder[0],args); 
                }
 
                // If the parameters and the args are not the same length or there is a paramArray 
                //  then we need to create a argument array.
                ParameterInfo[] parms = candidates[0].GetParametersNoCopy(); 

                if (parms.Length == args.Length)
                {
                    if (paramArrayTypes[0] != null) 
                    {
                        Object[] objs = new Object[parms.Length]; 
                        int lastPos = parms.Length - 1; 
                        Array.Copy(args, 0, objs, 0, lastPos);
                        objs[lastPos] = Array.UnsafeCreateInstance(paramArrayTypes[0], 1); 
                        ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
                        args = objs;
                    }
                } 
                else if (parms.Length > args.Length)
                { 
                    Object[] objs = new Object[parms.Length]; 

                    for (i=0;i args.Length)
            { 
                Object[] objs = new Object[parameters.Length];
 
                for (i=0;i binderState.m_originalSize) {
                    Object[] newArgs = new Object[binderState.m_originalSize]; 
                    Array.Copy(args, 0, newArgs, 0, binderState.m_originalSize);
                    args = newArgs;
                }
            } 
        }
 
        // Return any exact bindings that may exist. (This method is not defined on the 
        //  Binder and is used by RuntimeType.)
        public static MethodBase ExactBinding(MethodBase[] match,Type[] types,ParameterModifier[] modifiers) 
        {
            if (match==null)
                throw new ArgumentNullException("match");
            Contract.EndContractBlock(); 
            MethodBase[] aExactMatches = new MethodBase[match.Length];
            int cExactMatches = 0; 
 
            for (int i=0;i= p.Length - 1 is being put in the param array 

                if (paramArrayType1 != null && paramOrder1[i] >= p1.Length - 1)
                    c1 = paramArrayType1;
                else 
                    c1 = p1[paramOrder1[i]].ParameterType;
 
                if (paramArrayType2 != null && paramOrder2[i] >= p2.Length - 1) 
                    c2 = paramArrayType2;
                else 
                    c2 = p2[paramOrder2[i]].ParameterType;

                if (c1 == c2) continue;
 
                switch (FindMostSpecificType(c1, c2, types[i])) {
                    case 0: return 0; 
                    case 1: p1Less = true; break; 
                    case 2: p2Less = true; break;
                } 
            }

            // Two way p1Less and p2Less can be equal.  All the arguments are the
            //  same they both equal false, otherwise there were things that both 
            //  were the most specific type on....
            if (p1Less == p2Less) 
            { 
                // if we cannot tell which is a better match based on parameter types (p1Less == p2Less),
                // let's see which one has the most matches without using the params array (the longer one wins). 
                if (!p1Less && args != null)
                {
                    if (p1.Length > p2.Length)
                    { 
                        return 1;
                    } 
                    else if (p2.Length > p1.Length) 
                    {
                        return 2; 
                    }
                }

                return 0; 
            }
            else 
            { 
                return (p1Less == true) ? 1 : 2;
            } 
        }

        [System.Security.SecuritySafeCritical]  // auto-generated
        private static int FindMostSpecificType(Type c1, Type c2, Type t) 
        {
            // If the two types are exact move on... 
            if (c1 == c2) 
                return 0;
 
            if (c1 == t)
                return 1;

            if (c2 == t) 
                return 2;
 
            bool c1FromC2; 
            bool c2FromC1;
 
            if (c1.IsByRef || c2.IsByRef)
            {
                if (c1.IsByRef && c2.IsByRef)
                { 
                    c1 = c1.GetElementType();
                    c2 = c2.GetElementType(); 
                } 
                else if (c1.IsByRef)
                { 
                    if (c1.GetElementType() == c2)
                        return 2;

                    c1 = c1.GetElementType(); 
                }
                else 
                { 
                    if (c2.GetElementType() == c1)
                        return 1; 

                    c2 = c2.GetElementType();
                }
            } 

 
            if (c1.IsPrimitive && c2.IsPrimitive) 
            {
                c1FromC2 = CanConvertPrimitive((RuntimeType)c2, (RuntimeType)c1); 
                c2FromC1 = CanConvertPrimitive((RuntimeType)c1, (RuntimeType)c2);
            }
            else
            { 
                c1FromC2 = c1.IsAssignableFrom(c2);
                c2FromC1 = c2.IsAssignableFrom(c1); 
            } 

            if (c1FromC2 == c2FromC1) 
                return 0;

            if (c1FromC2)
            { 
                return 2;
            } 
            else 
            {
                return 1; 
            }
        }

        private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type paramArrayType1, 
                                                  MethodBase m2, int[] paramOrder2, Type paramArrayType2,
                                                  Type[] types, Object[] args) 
        { 
            // Find the most specific method based on the parameters.
            int res = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1, 
                                       m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args);

            // If the match was not ambigous then return the result.
            if (res != 0) 
                return res;
 
            // Check to see if the methods have the exact same name and signature. 
            if (CompareMethodSigAndName(m1, m2))
            { 
                // Determine the depth of the declaring types for both methods.
                int hierarchyDepth1 = GetHierarchyDepth(m1.DeclaringType);
                int hierarchyDepth2 = GetHierarchyDepth(m2.DeclaringType);
 
                // The most derived method is the most specific one.
                if (hierarchyDepth1 == hierarchyDepth2) 
                { 
                    return 0;
                } 
                else if (hierarchyDepth1 < hierarchyDepth2)
                {
                    return 2;
                } 
                else
                { 
                    return 1; 
                }
            } 

            // The match is ambigous.
            return 0;
        } 

        private static int FindMostSpecificField(FieldInfo cur1,FieldInfo cur2) 
        { 
            // Check to see if the fields have the same name.
            if (cur1.Name == cur2.Name) 
            {
                int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType);
                int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType);
 
                if (hierarchyDepth1 == hierarchyDepth2) {
                    Contract.Assert(cur1.IsStatic != cur2.IsStatic, "hierarchyDepth1 == hierarchyDepth2"); 
                    return 0; 
                }
                else if (hierarchyDepth1 < hierarchyDepth2) 
                    return 2;
                else
                    return 1;
            } 

            // The match is ambigous. 
            return 0; 
        }
 
        private static int FindMostSpecificProperty(PropertyInfo cur1,PropertyInfo cur2)
        {
            // Check to see if the fields have the same name.
            if (cur1.Name == cur2.Name) 
            {
                int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType); 
                int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType); 

                if (hierarchyDepth1 == hierarchyDepth2) { 
                    return 0;
                }
                else if (hierarchyDepth1 < hierarchyDepth2)
                    return 2; 
                else
                    return 1; 
            } 

            // The match is ambigous. 
            return 0;
        }

        internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2) 
        {
            ParameterInfo[] params1 = m1.GetParametersNoCopy(); 
            ParameterInfo[] params2 = m2.GetParametersNoCopy(); 

            if (params1.Length != params2.Length) 
                return false;

            int numParams = params1.Length;
            for (int i = 0; i < numParams; i++) 
            {
                if (params1[i].ParameterType != params2[i].ParameterType) 
                    return false; 
            }
 
            return true;
        }

        internal static int GetHierarchyDepth(Type t) 
        {
            int depth = 0; 
 
            Type currentType = t;
            do 
            {
                depth++;
                currentType = currentType.BaseType;
            } while (currentType != null); 

            return depth; 
        } 

        internal static MethodBase FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches) 
        {
            int deepestHierarchy = 0;
            MethodBase methWithDeepestHierarchy = null;
 
            for (int i = 0; i < cMatches; i++)
            { 
                // Calculate the depth of the hierarchy of the declaring type of the 
                // current method.
                int currentHierarchyDepth = GetHierarchyDepth(match[i].DeclaringType); 

                // The two methods have the same name, signature, and hierarchy depth.
                // This can only happen if at least one is vararg or generic.
                if (currentHierarchyDepth == deepestHierarchy) 
                {
                    throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); 
                } 

                // Check to see if this method is on the most derived class. 
                if (currentHierarchyDepth > deepestHierarchy)
                {
                    deepestHierarchy = currentHierarchyDepth;
                    methWithDeepestHierarchy = match[i]; 
                }
            } 
 
            return methWithDeepestHierarchy;
        } 

        // CanConvertPrimitive
        // This will determine if the source can be converted to the target type
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool CanConvertPrimitive(RuntimeType source,RuntimeType target); 

        // CanConvertPrimitiveObjectToType 
        // This method will determine if the primitive object can be converted
        //  to a type.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        static internal extern bool CanConvertPrimitiveObjectToType(Object source,RuntimeType type); 
 
        // This method will sort the vars array into the mapping order stored
        //  in the paramOrder array. 
        private static void ReorderParams(int[] paramOrder,Object[] vars)
        {
            object[] varsCopy = new object[vars.Length];
            for (int i = 0; i < vars.Length; i ++) 
                varsCopy[i] = vars[i];
 
            for (int i = 0; i < vars.Length; i ++) 
                vars[i] = varsCopy[paramOrder[i]];
        } 

        // This method will create the mapping between the Parameters and the underlying
        //  data based upon the names array.  The names array is stored in the same order
        //  as the values and maps to the parameters of the method.  We store the mapping 
        //  from the parameters to the names in the paramOrder array.  All parameters that
        //  don't have matching names are then stored in the array in order. 
        private static bool CreateParamOrder(int[] paramOrder,ParameterInfo[] pars,String[] names) 
        {
            bool[] used = new bool[pars.Length]; 

            // Mark which parameters have not been found in the names list
            for (int i=0;i

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK