diff options
Diffstat (limited to 'src/mscorlib/src/System/DefaultBinder.cs')
-rw-r--r-- | src/mscorlib/src/System/DefaultBinder.cs | 1162 |
1 files changed, 0 insertions, 1162 deletions
diff --git a/src/mscorlib/src/System/DefaultBinder.cs b/src/mscorlib/src/System/DefaultBinder.cs deleted file mode 100644 index b4681c406d..0000000000 --- a/src/mscorlib/src/System/DefaultBinder.cs +++ /dev/null @@ -1,1162 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -// -// 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; - 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. - // - 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"), nameof(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)) - { - 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; - } - 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;i++) - objs[i] = args[i]; - - for (;i<parms.Length - 1;i++) - objs[i] = parms[i].DefaultValue; - - if (paramArrayTypes[0] != null) - objs[i] = Array.UnsafeCreateInstance(paramArrayTypes[0], 0); // create an empty array for the - - else - objs[i] = parms[i].DefaultValue; - - args = objs; - } - else - { - if ((candidates[0].CallingConvention & CallingConventions.VarArgs) == 0) - { - Object[] objs = new Object[parms.Length]; - int paramArrayPos = parms.Length - 1; - Array.Copy(args, 0, objs, 0, paramArrayPos); - objs[paramArrayPos] = Array.UnsafeCreateInstance(paramArrayTypes[0], args.Length - paramArrayPos); - Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); - args = objs; - } - } - #endregion - - return candidates[0]; - } - - int currentMin = 0; - bool ambig = false; - for (i = 1; i < CurIdx; i++) - { - #region Walk all of the methods looking the most specific method to invoke - int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder[currentMin], paramArrayTypes[currentMin], - candidates[i], paramOrder[i], paramArrayTypes[i], argTypes, args); - - if (newMin == 0) - { - ambig = true; - } - else if (newMin == 2) - { - currentMin = i; - ambig = false; - } - #endregion - } - - if (ambig) - throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); - - // Reorder (if needed) - if (names != null) { - state = new BinderState((int[])paramOrder[currentMin].Clone(), args.Length, paramArrayTypes[currentMin] != null); - ReorderParams(paramOrder[currentMin], 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[] parameters = candidates[currentMin].GetParametersNoCopy(); - if (parameters.Length == args.Length) - { - if (paramArrayTypes[currentMin] != null) - { - Object[] objs = new Object[parameters.Length]; - int lastPos = parameters.Length - 1; - Array.Copy(args, 0, objs, 0, lastPos); - objs[lastPos] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], 1); - ((Array)objs[lastPos]).SetValue(args[lastPos], 0); - args = objs; - } - } - else if (parameters.Length > args.Length) - { - Object[] objs = new Object[parameters.Length]; - - for (i=0;i<args.Length;i++) - objs[i] = args[i]; - - for (;i<parameters.Length - 1;i++) - objs[i] = parameters[i].DefaultValue; - - if (paramArrayTypes[currentMin] != null) - { - objs[i] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], 0); - } - else - { - objs[i] = parameters[i].DefaultValue; - } - - args = objs; - } - else - { - if ((candidates[currentMin].CallingConvention & CallingConventions.VarArgs) == 0) - { - Object[] objs = new Object[parameters.Length]; - int paramArrayPos = parameters.Length - 1; - Array.Copy(args, 0, objs, 0, paramArrayPos); - objs[paramArrayPos] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos); - Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); - args = objs; - } - } - - return candidates[currentMin]; - } - - - // Given a set of fields that match the base criteria, select a field. - // if value is null then we have no way to select a field - public override FieldInfo BindToField(BindingFlags bindingAttr,FieldInfo[] match, Object value,CultureInfo cultureInfo) - { - if (match == null) { - throw new ArgumentNullException(nameof(match)); - } - - int i; - // Find the method that match... - int CurIdx = 0; - - Type valueType = null; - - FieldInfo[] candidates = (FieldInfo[]) match.Clone(); - - // If we are a FieldSet, then use the value's type to disambiguate - if ((bindingAttr & BindingFlags.SetField) != 0) { - valueType = value.GetType(); - - for (i=0;i<candidates.Length;i++) { - Type pCls = candidates[i].FieldType; - if (pCls == valueType) { - candidates[CurIdx++] = candidates[i]; - continue; - } - if (value == Empty.Value) { - // the object passed in was null which would match any non primitive non value type - if (pCls.IsClass) { - candidates[CurIdx++] = candidates[i]; - continue; - } - } - if (pCls == typeof(Object)) { - candidates[CurIdx++] = candidates[i]; - continue; - } - if (pCls.IsPrimitive) { - if (CanConvertPrimitiveObjectToType(value,(RuntimeType)pCls)) { - candidates[CurIdx++] = candidates[i]; - continue; - } - } - else { - if (pCls.IsAssignableFrom(valueType)) { - candidates[CurIdx++] = candidates[i]; - continue; - } - } - } - if (CurIdx == 0) - throw new MissingFieldException(Environment.GetResourceString("MissingField")); - if (CurIdx == 1) - return candidates[0]; - } - - // Walk all of the methods looking the most specific method to invoke - int currentMin = 0; - bool ambig = false; - for (i=1;i<CurIdx;i++) { - int newMin = FindMostSpecificField(candidates[currentMin], candidates[i]); - if (newMin == 0) - ambig = true; - else { - if (newMin == 2) { - currentMin = i; - ambig = false; - } - } - } - if (ambig) - throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); - return candidates[currentMin]; - } - - // Given a set of methods that match the base criteria, select a method based - // upon an array of types. This method should return null if no method matchs - // the criteria. - public override MethodBase SelectMethod(BindingFlags bindingAttr,MethodBase[] match,Type[] types,ParameterModifier[] modifiers) - { - int i; - int j; - - Type[] realTypes = new Type[types.Length]; - for (i=0;i<types.Length;i++) { - realTypes[i] = types[i].UnderlyingSystemType; - if (!(realTypes[i] is RuntimeType)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),nameof(types)); - } - types = realTypes; - - // We don't automatically jump out on exact match. - if (match == null || match.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), nameof(match)); - - MethodBase[] candidates = (MethodBase[]) match.Clone(); - - // Find all the methods that can be described by the types parameter. - // Remove all of them that cannot. - int CurIdx = 0; - for (i=0;i<candidates.Length;i++) { - ParameterInfo[] par = candidates[i].GetParametersNoCopy(); - if (par.Length != types.Length) - continue; - for (j=0;j<types.Length;j++) { - Type pCls = par[j].ParameterType; - if (pCls == types[j]) - continue; - if (pCls == typeof(Object)) - continue; - if (pCls.IsPrimitive) { - if (!(types[j].UnderlyingSystemType is RuntimeType) || - !CanConvertPrimitive((RuntimeType)types[j].UnderlyingSystemType,(RuntimeType)pCls.UnderlyingSystemType)) - break; - } - else { - if (!pCls.IsAssignableFrom(types[j])) - break; - } - } - if (j == types.Length) - candidates[CurIdx++] = candidates[i]; - } - if (CurIdx == 0) - return null; - if (CurIdx == 1) - return candidates[0]; - - // Walk all of the methods looking the most specific method to invoke - int currentMin = 0; - bool ambig = false; - int[] paramOrder = new int[types.Length]; - for (i=0;i<types.Length;i++) - paramOrder[i] = i; - for (i=1;i<CurIdx;i++) { - int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder, null, candidates[i], paramOrder, null, types, null); - if (newMin == 0) - ambig = true; - else { - if (newMin == 2) { - currentMin = i; - ambig = false; - currentMin = i; - } - } - } - if (ambig) - throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); - return candidates[currentMin]; - } - - // Given a set of properties that match the base criteria, select one. - public override PropertyInfo SelectProperty(BindingFlags bindingAttr,PropertyInfo[] match,Type returnType, - Type[] indexes,ParameterModifier[] modifiers) - { - // Allow a null indexes array. But if it is not null, every element must be non-null as well. - if (indexes != null && !Contract.ForAll(indexes, delegate(Type t) { return t != null; })) - { - throw new ArgumentNullException(nameof(indexes)); - } - if (match == null || match.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), nameof(match)); - Contract.EndContractBlock(); - - PropertyInfo[] candidates = (PropertyInfo[]) match.Clone(); - - int i,j = 0; - - // Find all the properties that can be described by type indexes parameter - int CurIdx = 0; - int indexesLength = (indexes != null) ? indexes.Length : 0; - for (i=0;i<candidates.Length;i++) { - - if (indexes != null) - { - ParameterInfo[] par = candidates[i].GetIndexParameters(); - if (par.Length != indexesLength) - continue; - - for (j=0;j<indexesLength;j++) { - Type pCls = par[j]. ParameterType; - - // If the classes exactly match continue - if (pCls == indexes[j]) - continue; - if (pCls == typeof(Object)) - continue; - - if (pCls.IsPrimitive) { - if (!(indexes[j].UnderlyingSystemType is RuntimeType) || - !CanConvertPrimitive((RuntimeType)indexes[j].UnderlyingSystemType,(RuntimeType)pCls.UnderlyingSystemType)) - break; - } - else { - if (!pCls.IsAssignableFrom(indexes[j])) - break; - } - } - } - - if (j == indexesLength) { - if (returnType != null) { - if (candidates[i].PropertyType.IsPrimitive) { - if (!(returnType.UnderlyingSystemType is RuntimeType) || - !CanConvertPrimitive((RuntimeType)returnType.UnderlyingSystemType,(RuntimeType)candidates[i].PropertyType.UnderlyingSystemType)) - continue; - } - else { - if (!candidates[i].PropertyType.IsAssignableFrom(returnType)) - continue; - } - } - candidates[CurIdx++] = candidates[i]; - } - } - if (CurIdx == 0) - return null; - if (CurIdx == 1) - return candidates[0]; - - // Walk all of the properties looking the most specific method to invoke - int currentMin = 0; - bool ambig = false; - int[] paramOrder = new int[indexesLength]; - for (i=0;i<indexesLength;i++) - paramOrder[i] = i; - for (i=1;i<CurIdx;i++) { - int newMin = FindMostSpecificType(candidates[currentMin].PropertyType, candidates[i].PropertyType,returnType); - if (newMin == 0 && indexes != null) - newMin = FindMostSpecific(candidates[currentMin].GetIndexParameters(), - paramOrder, - null, - candidates[i].GetIndexParameters(), - paramOrder, - null, - indexes, - null); - if (newMin == 0) - { - newMin = FindMostSpecificProperty(candidates[currentMin], candidates[i]); - if (newMin == 0) - ambig = true; - } - if (newMin == 2) { - ambig = false; - currentMin = i; - } - } - - if (ambig) - throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); - return candidates[currentMin]; - } - - // ChangeType - // The default binder doesn't support any change type functionality. - // This is because the default is built into the low level invoke code. - public override Object ChangeType(Object value,Type type,CultureInfo cultureInfo) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ChangeType")); - } - - public override void ReorderArgumentArray(ref Object[] args, Object state) - { - BinderState binderState = (BinderState)state; - ReorderParams(binderState.m_argsMap, args); - if (binderState.m_isParamArray) { - int paramArrayPos = args.Length - 1; - if (args.Length == binderState.m_originalSize) - args[paramArrayPos] = ((Object[])args[paramArrayPos])[0]; - else { - // must be args.Length < state.originalSize - Object[] newArgs = new Object[args.Length]; - Array.Copy(args, 0, newArgs, 0, paramArrayPos); - for (int i = paramArrayPos, j = 0; i < newArgs.Length; i++, j++) { - newArgs[i] = ((Object[])args[paramArrayPos])[j]; - } - args = newArgs; - } - } - else { - if (args.Length > 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(nameof(match)); - Contract.EndContractBlock(); - MethodBase[] aExactMatches = new MethodBase[match.Length]; - int cExactMatches = 0; - - for (int i=0;i<match.Length;i++) { - ParameterInfo[] par = match[i].GetParametersNoCopy(); - if (par.Length == 0) { - continue; - } - int j; - for (j=0;j<types.Length;j++) { - Type pCls = par[j]. ParameterType; - - // If the classes exactly match continue - if (!pCls.Equals(types[j])) - break; - } - if (j < types.Length) - continue; - - // Add the exact match to the array of exact matches. - aExactMatches[cExactMatches] = match[i]; - cExactMatches++; - } - - if (cExactMatches == 0) - return null; - - if (cExactMatches == 1) - return aExactMatches[0]; - - return FindMostDerivedNewSlotMeth(aExactMatches, cExactMatches); - } - - // Return any exact bindings that may exist. (This method is not defined on the - // Binder and is used by RuntimeType.) - public static PropertyInfo ExactPropertyBinding(PropertyInfo[] match,Type returnType,Type[] types,ParameterModifier[] modifiers) - { - if (match==null) - throw new ArgumentNullException(nameof(match)); - Contract.EndContractBlock(); - - PropertyInfo bestMatch = null; - int typesLength = (types != null) ? types.Length : 0; - for (int i=0;i<match.Length;i++) { - ParameterInfo[] par = match[i].GetIndexParameters(); - int j; - for (j=0;j<typesLength;j++) { - Type pCls = par[j].ParameterType; - - // If the classes exactly match continue - if (pCls != types[j]) - break; - } - if (j < typesLength) - continue; - if (returnType != null && returnType != match[i].PropertyType) - continue; - - if (bestMatch != null) - throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException")); - - bestMatch = match[i]; - } - return bestMatch; - } - - private static int FindMostSpecific(ParameterInfo[] p1, int[] paramOrder1, Type paramArrayType1, - ParameterInfo[] p2, int[] paramOrder2, Type paramArrayType2, - Type[] types, Object[] args) - { - // A method using params is always less specific than one not using params - if (paramArrayType1 != null && paramArrayType2 == null) return 2; - if (paramArrayType2 != null && paramArrayType1 == null) return 1; - - // now either p1 and p2 both use params or neither does. - - bool p1Less = false; - bool p2Less = false; - - for (int i = 0; i < types.Length; i++) - { - if (args != null && args[i] == Type.Missing) - continue; - - Type c1, c2; - - // If a param array is present, then either - // the user re-ordered the parameters in which case - // the argument to the param array is either an array - // in which case the params is conceptually ignored and so paramArrayType1 == null - // or the argument to the param array is a single element - // in which case paramOrder[i] == p1.Length - 1 for that element - // or the user did not re-order the parameters in which case - // the paramOrder array could contain indexes larger than p.Length - 1 (see VSW 577286) - // so any index >= 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; - } - } - - 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) { - Debug.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 - [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. - [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<pars.Length;i++) - paramOrder[i] = -1; - // Find the parameters with names. - for (int i=0;i<names.Length;i++) { - int j; - for (j=0;j<pars.Length;j++) { - if (names[i].Equals(pars[j].Name)) { - paramOrder[j] = i; - used[i] = true; - break; - } - } - // This is an error condition. The name was not found. This - // method must not match what we sent. - if (j == pars.Length) - return false; - } - - // Now we fill in the holes with the parameters that are unused. - int pos = 0; - for (int i=0;i<pars.Length;i++) { - if (paramOrder[i] == -1) { - for (;pos<pars.Length;pos++) { - if (!used[pos]) { - paramOrder[i] = pos; - pos++; - break; - } - } - } - } - return true; - } - - internal class BinderState { - internal int[] m_argsMap; - internal int m_originalSize; - internal bool m_isParamArray; - - internal BinderState(int[] argsMap, int originalSize, bool isParamArray) { - m_argsMap = argsMap; - m_originalSize = originalSize; - m_isParamArray = isParamArray; - } - - } - - } -} |