The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ JSBinder

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Reflection;
  20.     using System.Globalization;
  21.     using System.Collections;
  22.     using System.Runtime.InteropServices;
  23.    
  24.     [Serializable()]
  25.     internal sealed class JSBinder : Binder
  26.     {
  27.         static internal readonly JSBinder ob = new JSBinder();
  28.        
  29.         // both args and namedParameters cannot be null and args length must be bigger or equal to namedParameters.Length
  30.         static internal object[] ArrangeNamedArguments(MethodBase method, object[] args, string[] namedParameters)
  31.         {
  32.             ParameterInfo[] pars = method.GetParameters();
  33.             int formalLength = pars.Length;
  34.             if (formalLength == 0)
  35.                 throw new JScriptException(JSError.MissingNameParameter);
  36.             object[] newArgs = new object[formalLength];
  37.             int argsLength = args.Length;
  38.             int namesLength = namedParameters.Length;
  39.             int numPositional = argsLength - namesLength;
  40.             ArrayObject.Copy(args, namesLength, newArgs, 0, numPositional);
  41.             for (int i = 0; i < namesLength; i++) {
  42.                 string name = namedParameters[i];
  43.                 if (name == null || name.Equals(""))
  44.                     throw new JScriptException(JSError.MustProvideNameForNamedParameter);
  45.                 int j;
  46.                 for (j = numPositional; j < formalLength; j++) {
  47.                     if (name.Equals(pars[j].Name))
  48.                         if (newArgs[j] is Empty)
  49.                             throw new JScriptException(JSError.DuplicateNamedParameter);
  50.                         else {
  51.                             newArgs[j] = args[i];
  52.                             break;
  53.                         }
  54.                 }
  55.                 if (j == formalLength)
  56.                     throw new JScriptException(JSError.MissingNameParameter);
  57.             }
  58.             // go through the array and replace null/missing entries with the default value of the corresponding param (if any)
  59.             if (method is JSMethod)
  60.                 return newArgs;
  61.             //JSMethods get special treatment elsewhere
  62.             for (int i = 0; i < formalLength; i++)
  63.                 if (newArgs[i] == null || newArgs[i] == Missing.Value) {
  64.                     object dv = TypeReferences.GetDefaultParameterValue(pars[i]);
  65.                     if (dv == System.Convert.DBNull)
  66.                         //No default value was specified
  67.                         throw new ArgumentException(pars[i].Name);
  68.                     newArgs[i] = dv;
  69.                 }
  70.             return newArgs;
  71.         }
  72.        
  73.         public override FieldInfo BindToField(BindingFlags bindAttr, FieldInfo[] match, object value, CultureInfo locale)
  74.         {
  75.             if (value == null)
  76.                 value = DBNull.Value;
  77.             int minval = Int32.MaxValue;
  78.             int dupCount = 0;
  79.             FieldInfo bestField = null;
  80.             Type vtype = value.GetType();
  81.             for (int i = 0int j = match.Length; i < j; i++) {
  82.                 FieldInfo field = match[i];
  83.                 int distance = TypeDistance(Runtime.TypeRefs, field.FieldType, vtype);
  84.                 if (distance < minval) {
  85.                     minval = distance;
  86.                     bestField = field;
  87.                     dupCount = 0;
  88.                 }
  89.                 else if (distance == minval)
  90.                     dupCount += 1;
  91.             }
  92.             if (dupCount > 0)
  93.                 throw new AmbiguousMatchException();
  94.             return bestField;
  95.         }
  96.        
  97.         public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo locale, string[] namedParameters, out object state)
  98.         {
  99.             state = null;
  100.             return JSBinder.SelectMethodBase(Runtime.TypeRefs, match, ref args, modifiers, namedParameters);
  101.         }
  102.        
  103.         public override object ChangeType(object value, Type target_type, CultureInfo locale)
  104.         {
  105.             return Convert.CoerceT(value, target_type);
  106.         }
  107.        
  108.         static internal MemberInfo[] GetDefaultMembers(IReflect ir)
  109.         {
  110.             return JSBinder.GetDefaultMembers(Globals.TypeRefs, ir);
  111.         }
  112.        
  113.         static internal MemberInfo[] GetDefaultMembers(TypeReferences typeRefs, IReflect ir)
  114.         {
  115.             while (ir is ClassScope) {
  116.                 ClassScope csc = (ClassScope)ir;
  117.                 csc.owner.IsExpando();
  118.                 //Force the class to expose its expando property if it has not already done so
  119.                 if (csc.itemProp != null)
  120.                     return new MemberInfo[] {csc.itemProp};
  121.                 ir = csc.GetParent();
  122.                 if (ir is WithObject)
  123.                     ir = (IReflect)((WithObject)ir).contained_object;
  124.             }
  125.             if (ir is Type)
  126.                 return JSBinder.GetDefaultMembers((Type)ir);
  127.             if (ir is JSObject)
  128.                 return typeRefs.ScriptObject.GetDefaultMembers();
  129.             return null;
  130.         }
  131.        
  132.         static internal MemberInfo[] GetDefaultMembers(Type t)
  133.         {
  134.             while (t != typeof(object) && t != null) {
  135.                 MemberInfo[] defaultMembers = t.GetDefaultMembers();
  136.                 if (defaultMembers != null && defaultMembers.Length > 0)
  137.                     return defaultMembers;
  138.                 t = t.BaseType;
  139.             }
  140.             return null;
  141.         }
  142.        
  143.         static internal MethodInfo GetDefaultPropertyForArrayIndex(Type t, int index, Type elementType, bool getSetter)
  144.         {
  145.             try {
  146.                 MemberInfo[] defaultMembers = JSBinder.GetDefaultMembers(Runtime.TypeRefs, t);
  147.                 int n = 0;
  148.                 if (defaultMembers == null || (n = defaultMembers.Length) == 0)
  149.                     return null;
  150.                 for (int i = 0; i < n; i++) {
  151.                     MemberInfo mem = defaultMembers[i];
  152.                     MemberTypes mt = mem.MemberType;
  153.                     MethodInfo meth = null;
  154.                     switch (mt) {
  155.                         case MemberTypes.Property:
  156.                             meth = ((PropertyInfo)mem).GetGetMethod();
  157.                             break;
  158.                         case MemberTypes.Method:
  159.                             meth = (MethodInfo)mem;
  160.                             break;
  161.                         default:
  162.                             continue;
  163.                     }
  164.                     if (meth != null) {
  165.                         ParameterInfo[] pars = meth.GetParameters();
  166.                         if (pars == null || pars.Length == 0) {
  167.                             //See if meth is a default method/property-getter that returns an Array or List
  168.                             Type rt = meth.ReturnType;
  169.                             if (typeof(Array).IsAssignableFrom(rt) || typeof(IList).IsAssignableFrom(rt))
  170.                                 return meth;
  171.                         }
  172.                         else if (pars.Length == 1 && mt == MemberTypes.Property) {
  173.                             //See if meth is the getter of a suitable default indexed property
  174.                             PropertyInfo prop = (PropertyInfo)mem;
  175.                             if (elementType == null || prop.PropertyType.IsAssignableFrom(elementType))
  176.                                 try {
  177.                                     Convert.CoerceT(index, pars[0].ParameterType);
  178.                                     if (getSetter)
  179.                                         return prop.GetSetMethod();
  180.                                     else
  181.                                         return meth;
  182.                                 }
  183.                                 catch (JScriptException) {
  184.                                 }
  185.                         }
  186.                     }
  187.                 }
  188.             }
  189.             catch (InvalidOperationException) {
  190.             }
  191.             return null;
  192.         }
  193.        
  194.         static internal MemberInfo[] GetInterfaceMembers(string name, Type t)
  195.         {
  196.             BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
  197.             MemberInfo[] members = t.GetMember(name, flags);
  198.             Type[] baseInts = t.GetInterfaces();
  199.             if (baseInts == null || baseInts.Length == 0)
  200.                 return members;
  201.             ArrayList baseInterfaces = new ArrayList(baseInts);
  202.             MemberInfoList result = new MemberInfoList();
  203.             result.AddRange(members);
  204.             for (int i = 0; i < baseInterfaces.Count; i++) {
  205.                 Type bi = (Type)baseInterfaces[i];
  206.                 members = bi.GetMember(name, flags);
  207.                 if (members != null)
  208.                     result.AddRange(members);
  209.                 foreach (Type bbi in bi.GetInterfaces()) {
  210.                     if (baseInterfaces.IndexOf(bbi) == -1)
  211.                         baseInterfaces.Add(bbi);
  212.                 }
  213.             }
  214.             return result.ToArray();
  215.         }
  216.        
  217.         private static bool FormalParamTypeIsObject(ParameterInfo par)
  218.         {
  219.             ParameterDeclaration pd = par as ParameterDeclaration;
  220.             if (pd != null)
  221.                 return pd.ParameterIReflect == Typeob.Object;
  222.             return par.ParameterType == Typeob.Object;
  223.         }
  224.        
  225.         public override void ReorderArgumentArray(ref object[] args, object state)
  226.         {
  227.         }
  228.        
  229.         static internal MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, MemberTypes memberType)
  230.         {
  231.             Debug.Assert(matches > 1);
  232.             int candidates = 0;
  233.             ParameterInfo[][] fparams = new ParameterInfo[matches][];
  234.             bool lookForPropertyGetters = memberType == MemberTypes.Method;
  235.             for (int i = 0; i < matches; i++) {
  236.                 MemberInfo mem = match[i];
  237.                 if (mem is PropertyInfo && lookForPropertyGetters)
  238.                     mem = ((PropertyInfo)mem).GetGetMethod(true);
  239.                 if (mem == null)
  240.                     continue;
  241.                 if (mem.MemberType == memberType) {
  242.                     if (mem is PropertyInfo)
  243.                         fparams[i] = ((PropertyInfo)mem).GetIndexParameters();
  244.                     else
  245.                         fparams[i] = ((MethodBase)mem).GetParameters();
  246.                     candidates++;
  247.                 }
  248.             }
  249.             int j = JSBinder.SelectBest(typeRefs, match, matches, argIRs, fparams, null, candidates, argIRs.Length);
  250.             if (j < 0)
  251.                 return null;
  252.             return match[j];
  253.         }
  254.        
  255.         static internal MemberInfo Select(TypeReferences typeRefs, MemberInfo[] match, int matches, ref object[] args, string[] namedParameters, MemberTypes memberType)
  256.         {
  257.             Debug.Assert(matches > 1);
  258.             bool hasNamedParams = false;
  259.             if (namedParameters != null && namedParameters.Length > 0)
  260.                 if (args.Length >= namedParameters.Length)
  261.                     hasNamedParams = true;
  262.                 else
  263.                     throw new JScriptException(JSError.MoreNamedParametersThanArguments);
  264.             int candidates = 0;
  265.             ParameterInfo[][] fparams = new ParameterInfo[matches][];
  266.             object[][] aparams = new object[matches][];
  267.             bool lookForPropertyGetters = memberType == MemberTypes.Method;
  268.             for (int i = 0; i < matches; i++) {
  269.                 MemberInfo mem = match[i];
  270.                 if (lookForPropertyGetters && mem.MemberType == MemberTypes.Property)
  271.                     mem = ((PropertyInfo)mem).GetGetMethod(true);
  272.                 if (mem.MemberType == memberType) {
  273.                     if (memberType == MemberTypes.Property)
  274.                         fparams[i] = ((PropertyInfo)mem).GetIndexParameters();
  275.                     else
  276.                         fparams[i] = ((MethodBase)mem).GetParameters();
  277.                     if (hasNamedParams)
  278.                         aparams[i] = JSBinder.ArrangeNamedArguments((MethodBase)mem, args, namedParameters);
  279.                     else
  280.                         aparams[i] = args;
  281.                     candidates++;
  282.                 }
  283.             }
  284.             int j = JSBinder.SelectBest(typeRefs, match, matches, null, fparams, aparams, candidates, args.Length);
  285.             if (j < 0)
  286.                 return null;
  287.             args = aparams[j];
  288.             MemberInfo result = match[j];
  289.             if (lookForPropertyGetters && result.MemberType == MemberTypes.Property)
  290.                 result = ((PropertyInfo)result).GetGetMethod(true);
  291.             return result;
  292.         }
  293.        
  294.         private static int SelectBest(TypeReferences typeRefs, MemberInfo[] match, int matches, IReflect[] argIRs, ParameterInfo[][] fparams, object[][] aparams, int candidates, int parameters)
  295.         {
  296.             Debug.Assert(matches > 1);
  297.             if (candidates == 0)
  298.                 return -1;
  299.             if (candidates == 1)
  300.                 for (int i = 0; i < matches; i++)
  301.                     if (fparams[i] != null)
  302.                         return i;
  303.             bool[] eliminated = new bool[matches];
  304.             //Set up penalties to discourage selection of methods that have more formal parameters than there are actual parameters
  305.             int[] penalty = new int[matches];
  306.             for (int i = 0; i < matches; i++) {
  307.                 ParameterInfo[] fpars = fparams[i];
  308.                 if (fpars != null) {
  309.                     int m = fpars.Length;
  310.                     int actuals = (argIRs == null ? aparams[i].Length : argIRs.Length);
  311.                     if (actuals > m && (m == 0 || !CustomAttribute.IsDefined(fpars[m - 1], typeof(ParamArrayAttribute), false))) {
  312.                         fparams[i] = null;
  313.                         candidates--;
  314.                         Debug.Assert(candidates >= 0);
  315.                         continue;
  316.                     }
  317.                     for (int j = parameters; j < m; j++) {
  318.                         ParameterInfo fpar = fpars[j];
  319.                         if (j == m - 1 && CustomAttribute.IsDefined(fpar, typeof(ParamArrayAttribute), false))
  320.                             break;
  321.                         object dv = TypeReferences.GetDefaultParameterValue(fpar);
  322.                         if (dv is System.DBNull) {
  323.                             //No default value, set up a penalty
  324.                             penalty[i] = 50;
  325.                         }
  326.                     }
  327.                 }
  328.             }
  329.             for (int p = 0; candidates > 1; p++) {
  330.                 int candidatesWithFormalParametersStillToBeConsidered = 0;
  331.                 //Eliminate any candidate that is worse match than any other candidate for this (possibly missing) actual parameter
  332.                 int minval = Int32.MaxValue;
  333.                 bool objectCanWin = false;
  334.                 for (int i = 0; i < matches; i++) {
  335.                     int penaltyForUsingDefaultValue = 0;
  336.                     ParameterInfo[] fpars = fparams[i];
  337.                     if (fpars != null) {
  338.                         //match[i] is a candidate
  339.                         IReflect aIR = typeRefs.Missing;
  340.                         if (argIRs == null) {
  341.                             if (aparams[i].Length > p) {
  342.                                 object apar = aparams[i][p];
  343.                                 if (apar == null)
  344.                                     apar = DBNull.Value;
  345.                                 aIR = typeRefs.ToReferenceContext(apar.GetType());
  346.                             }
  347.                         }
  348.                         else if (p < parameters)
  349.                             aIR = argIRs[p];
  350.                         int m = fpars.Length;
  351.                         if (m - 1 > p)
  352.                             candidatesWithFormalParametersStillToBeConsidered++;
  353.                         IReflect fIR = typeRefs.Missing;
  354.                         if (m > 0 && p >= m - 1 && CustomAttribute.IsDefined(fpars[m - 1], typeof(ParamArrayAttribute), false) && !(aIR is TypedArray || aIR == typeRefs.ArrayObject || (aIR is Type && ((Type)aIR).IsArray))) {
  355.                             ParameterInfo fpar = fpars[m - 1];
  356.                             if (fpar is ParameterDeclaration) {
  357.                                 fIR = ((ParameterDeclaration)fpar).ParameterIReflect;
  358.                                 fIR = ((TypedArray)fIR).elementType;
  359.                             }
  360.                             else
  361.                                 fIR = fpar.ParameterType.GetElementType();
  362.                             if (p == m - 1)
  363.                                 penalty[i]++;
  364.                         }
  365.                         else if (p < m) {
  366.                             ParameterInfo fpar = fpars[p];
  367.                             fIR = fpar is ParameterDeclaration ? ((ParameterDeclaration)fpar).ParameterIReflect : fpar.ParameterType;
  368.                             if (aIR == typeRefs.Missing) {
  369.                                 //No actual parameter was supplied, if the formal parameter has default value, make the match perfect
  370.                                 object dv = TypeReferences.GetDefaultParameterValue(fpar);
  371.                                 if (!(dv is System.DBNull)) {
  372.                                     aIR = fIR;
  373.                                     penaltyForUsingDefaultValue = 1;
  374.                                 }
  375.                             }
  376.                         }
  377.                         int distance = TypeDistance(typeRefs, fIR, aIR) + penalty[i] + penaltyForUsingDefaultValue;
  378.                         if (distance == minval) {
  379.                             if (p == m - 1 && eliminated[i]) {
  380.                                 candidates--;
  381.                                 fparams[i] = null;
  382.                             }
  383.                             objectCanWin = objectCanWin && eliminated[i];
  384.                             continue;
  385.                         }
  386.                         if (distance > minval) {
  387.                             if (objectCanWin && p < m && JSBinder.FormalParamTypeIsObject(fparams[i][p])) {
  388.                                 minval = distance;
  389.                                 //Make sure that a future, better match than Object can win.
  390.                                 continue;
  391.                             }
  392.                             if (p > m - 1 && aIR == typeRefs.Missing && CustomAttribute.IsDefined(fpars[m - 1], typeof(ParamArrayAttribute), false))
  393.                                 continue;
  394.                             eliminated[i] = true;
  395.                             continue;
  396.                         }
  397.                         //If we get here, we have a match that is strictly better than all previous matches.
  398.                         //If there are no other remaining candidates, we're done.
  399.                         if (candidates == 1 && !eliminated[i])
  400.                             return i;
  401.                         //Eliminate those other candidates from consideration.
  402.                         objectCanWin = eliminated[i];
  403.                         for (int j = 0; j < i; j++)
  404.                             if (fparams[j] != null && !eliminated[j]) {
  405.                                 bool noFormalForCurrParam = fparams[j].Length <= p;
  406.                                 if (noFormalForCurrParam && parameters <= p)
  407.                                     //Do not eliminate an overload if it does not have a formal for the current position
  408.                                     //and the call does not have an actual parameter for the current position either.
  409.                                     continue;
  410.                                 if (noFormalForCurrParam || !objectCanWin || !JSBinder.FormalParamTypeIsObject(fparams[j][p]))
  411.                                     eliminated[j] = true;
  412.                             }
  413.                         minval = distance;
  414.                     }
  415.                 }
  416.                 if (p >= parameters - 1 && candidatesWithFormalParametersStillToBeConsidered < 1)
  417.                     //Looked at all actual parameters as well as all formal parameters, no further progress can be made
  418.                     break;
  419.             }
  420.             int best = -1;
  421.             for (int j = 0; j < matches && candidates > 0; j++) {
  422.                 ParameterInfo[] fpars = fparams[j];
  423.                 if (fpars != null) {
  424.                     if (eliminated[j]) {
  425.                         candidates--;
  426.                         fparams[j] = null;
  427.                         continue;
  428.                     }
  429.                     int pc = fpars.Length;
  430.                     if (best == -1) {
  431.                         //Choose the first remaining candidate as "best"
  432.                         best = j;
  433.                         continue;
  434.                     }
  435.                     if (Class.ParametersMatch(fpars, fparams[best])) {
  436.                         MemberInfo bstm = match[best];
  437.                         JSWrappedMethod jswm = match[best] as JSWrappedMethod;
  438.                         if (jswm != null)
  439.                             bstm = jswm.method;
  440.                         if (bstm is JSFieldMethod || bstm is JSConstructor || bstm is JSProperty) {
  441.                             //The first match is always the most derived, go with it
  442.                             candidates--;
  443.                             fparams[j] = null;
  444.                             continue;
  445.                         }
  446.                         Type bestMemT = match[best].DeclaringType;
  447.                         Type memT = match[j].DeclaringType;
  448.                         if (bestMemT != memT) {
  449.                             if (memT.IsAssignableFrom(bestMemT)) {
  450.                                 candidates--;
  451.                                 fparams[j] = null;
  452.                                 continue;
  453.                             }
  454.                             else if (bestMemT.IsAssignableFrom(memT)) {
  455.                                 fparams[best] = null;
  456.                                 best = j;
  457.                                 candidates--;
  458.                                 continue;
  459.                             }
  460.                         }
  461.                     }
  462.                 }
  463.             }
  464.             if (candidates != 1)
  465.                 throw new AmbiguousMatchException();
  466.             return best;
  467.         }
  468.        
  469.        
  470.         static internal ConstructorInfo SelectConstructor(MemberInfo[] match, ref object[] args, string[] namedParameters)
  471.         {
  472.             return JSBinder.SelectConstructor(Globals.TypeRefs, match, ref args, namedParameters);
  473.         }
  474.        
  475.         static internal ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, ref object[] args, string[] namedParameters)
  476.         {
  477.             if (match == null)
  478.                 return null;
  479.             int n = match.Length;
  480.             if (n == 0)
  481.                 return null;
  482.             if (n == 1) {
  483.                 Type t = match[0] as Type;
  484.                 if (t != null) {
  485.                     match = t.GetConstructors();
  486.                     n = match.Length;
  487.                 }
  488.             }
  489.             if (n == 1)
  490.                 return match[0] as ConstructorInfo;
  491.             return (ConstructorInfo)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Constructor);
  492.         }
  493.        
  494.         static internal ConstructorInfo SelectConstructor(MemberInfo[] match, IReflect[] argIRs)
  495.         {
  496.             return JSBinder.SelectConstructor(Globals.TypeRefs, match, argIRs);
  497.         }
  498.        
  499.         static internal ConstructorInfo SelectConstructor(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs)
  500.         {
  501.             if (match == null)
  502.                 return null;
  503.             int n = match.Length;
  504.             if (n == 1) {
  505.                 object val = match[0];
  506.                 if (val is JSGlobalField)
  507.                     val = ((JSGlobalField)val).GetValue(null);
  508.                 Type t = val as Type;
  509.                 if (t != null) {
  510.                     match = t.GetConstructors();
  511.                 }
  512.                 n = match.Length;
  513.             }
  514.             if (n == 0)
  515.                 return null;
  516.             if (n == 1)
  517.                 return match[0] as ConstructorInfo;
  518.             return (ConstructorInfo)JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Constructor);
  519.         }
  520.        
  521.         static internal MemberInfo SelectCallableMember(MemberInfo[] match, IReflect[] argIRs)
  522.         {
  523.             if (match == null)
  524.                 return null;
  525.             int n = match.Length;
  526.             if (n == 0)
  527.                 return null;
  528.             MemberInfo result = n == 1 ? match[0] : JSBinder.Select(Globals.TypeRefs, match, n, argIRs, MemberTypes.Method);
  529.             return result as MemberInfo;
  530.         }
  531.        
  532.         static internal MethodInfo SelectMethod(MemberInfo[] match, ref object[] args, string[] namedParameters)
  533.         {
  534.             return JSBinder.SelectMethod(Globals.TypeRefs, match, ref args, namedParameters);
  535.         }
  536.        
  537.         static internal MethodInfo SelectMethod(TypeReferences typeRefs, MemberInfo[] match, ref object[] args, string[] namedParameters)
  538.         {
  539.             if (match == null)
  540.                 return null;
  541.             int n = match.Length;
  542.             if (n == 0)
  543.                 return null;
  544.             MemberInfo result = n == 1 ? match[0] : JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Method);
  545.             if (result != null && result.MemberType == MemberTypes.Property)
  546.                 result = ((PropertyInfo)result).GetGetMethod(true);
  547.             return result as MethodInfo;
  548.         }
  549.        
  550.         static internal MethodInfo SelectMethod(MemberInfo[] match, IReflect[] argIRs)
  551.         {
  552.             return JSBinder.SelectMethod(Globals.TypeRefs, match, argIRs);
  553.         }
  554.        
  555.         static internal MethodInfo SelectMethod(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs)
  556.         {
  557.             if (match == null)
  558.                 return null;
  559.             int n = match.Length;
  560.             if (n == 0)
  561.                 return null;
  562.             MemberInfo result = n == 1 ? match[0] : JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Method);
  563.             if (result != null && result.MemberType == MemberTypes.Property)
  564.                 return ((PropertyInfo)result).GetGetMethod(true);
  565.             return result as MethodInfo;
  566.         }
  567.        
  568.         public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
  569.         {
  570.             if (match == null)
  571.                 return null;
  572.             int n = match.Length;
  573.             if (n == 0)
  574.                 return null;
  575.             if (n == 1)
  576.                 return match[0];
  577.             if (match[0].MemberType == MemberTypes.Constructor)
  578.                 return (ConstructorInfo)JSBinder.Select(Runtime.TypeRefs, match, n, types, MemberTypes.Constructor);
  579.             else
  580.                 return (MethodInfo)JSBinder.Select(Runtime.TypeRefs, match, n, types, MemberTypes.Method);
  581.         }
  582.        
  583.         private static MethodBase SelectMethodBase(TypeReferences typeRefs, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, string[] namedParameters)
  584.         {
  585.             if (match == null)
  586.                 return null;
  587.             int n = match.Length;
  588.             if (n == 0)
  589.                 return null;
  590.             if (n == 1)
  591.                 return match[0];
  592.             MethodBase result = (MethodBase)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Method);
  593.             if (result == null)
  594.                 result = (MethodBase)JSBinder.Select(typeRefs, match, n, ref args, namedParameters, MemberTypes.Constructor);
  595.             return result;
  596.         }
  597.        
  598.         static internal MethodInfo SelectOperator(MethodInfo op1, MethodInfo op2, Type t1, Type t2)
  599.         {
  600.             ParameterInfo[] params1 = null;
  601.             if (op1 == null || (op1.Attributes & MethodAttributes.SpecialName) == 0 || (params1 = op1.GetParameters()).Length != 2)
  602.                 op1 = null;
  603.             ParameterInfo[] params2 = null;
  604.             if (op2 == null || (op2.Attributes & MethodAttributes.SpecialName) == 0 || (params2 = op2.GetParameters()).Length != 2)
  605.                 op2 = null;
  606.             if (op1 == null)
  607.                 return op2;
  608.             if (op2 == null)
  609.                 return op1;
  610.             int op1cost = TypeDistance(Globals.TypeRefs, params1[0].ParameterType, t1) + TypeDistance(Globals.TypeRefs, params1[1].ParameterType, t2);
  611.             int op2cost = TypeDistance(Globals.TypeRefs, params2[0].ParameterType, t1) + TypeDistance(Globals.TypeRefs, params2[1].ParameterType, t2);
  612.             if (op1cost <= op2cost)
  613.                 return op1;
  614.             return op2;
  615.         }
  616.        
  617.         static internal PropertyInfo SelectProperty(MemberInfo[] match, object[] args)
  618.         {
  619.             return JSBinder.SelectProperty(Globals.TypeRefs, match, args);
  620.         }
  621.        
  622.         static internal PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, object[] args)
  623.         {
  624.             if (match == null)
  625.                 return null;
  626.             int matches = match.Length;
  627.             if (matches == 0)
  628.                 return null;
  629.             if (matches == 1)
  630.                 return match[0] as PropertyInfo;
  631.             int candidates = 0;
  632.             PropertyInfo result = null;
  633.             ParameterInfo[][] fparams = new ParameterInfo[matches][];
  634.             object[][] aparams = new object[matches][];
  635.             for (int i = 0; i < matches; i++) {
  636.                 MemberInfo mem = match[i];
  637.                 if (mem.MemberType == MemberTypes.Property) {
  638.                     MethodInfo getter = (result = (PropertyInfo)mem).GetGetMethod(true);
  639.                     if (getter == null)
  640.                         fparams[i] = result.GetIndexParameters();
  641.                     else
  642.                         fparams[i] = getter.GetParameters();
  643.                     aparams[i] = args;
  644.                     candidates++;
  645.                 }
  646.             }
  647.             if (candidates <= 1)
  648.                 return result;
  649.             int j = JSBinder.SelectBest(typeRefs, match, matches, null, fparams, aparams, candidates, args.Length);
  650.             if (j < 0)
  651.                 return null;
  652.             return (PropertyInfo)match[j];
  653.         }
  654.        
  655.         public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type rtype, Type[] types, ParameterModifier[] modifiers)
  656.         {
  657.             if (match == null)
  658.                 return null;
  659.             int matches = match.Length;
  660.             if (matches == 0)
  661.                 return null;
  662.             if (matches == 1)
  663.                 return match[0];
  664.             int candidates = 0;
  665.             PropertyInfo result = null;
  666.             int minval = Int32.MaxValue;
  667.             ParameterInfo[][] fparams = new ParameterInfo[matches][];
  668.             for (int i = 0; i < matches; i++) {
  669.                 result = match[i];
  670.                 if (rtype != null) {
  671.                     int distance = TypeDistance(Globals.TypeRefs, result.PropertyType, rtype);
  672.                     if (distance > minval)
  673.                         continue;
  674.                     if (distance < minval)
  675. //This property is strictly a better than all previous one w.r.t. rtype. Remove all of those from consideration
  676.                         for (int j = 0; j < i; j++)
  677.                             if (fparams[j] != null) {
  678.                                 fparams[j] = null;
  679.                                 candidates--;
  680.                             }
  681.                 }
  682.                 fparams[i] = result.GetIndexParameters();
  683.                 candidates++;
  684.             }
  685.             if (candidates <= 1)
  686.                 return result;
  687.             int k = JSBinder.SelectBest(Globals.TypeRefs, match, matches, types, fparams, null, candidates, types.Length);
  688.             if (k < 0)
  689.                 return null;
  690.             return match[k];
  691.         }
  692.        
  693.         static internal PropertyInfo SelectProperty(MemberInfo[] match, IReflect[] argIRs)
  694.         {
  695.             return JSBinder.SelectProperty(Globals.TypeRefs, match, argIRs);
  696.         }
  697.        
  698.         static internal PropertyInfo SelectProperty(TypeReferences typeRefs, MemberInfo[] match, IReflect[] argIRs)
  699.         {
  700.             if (match == null)
  701.                 return null;
  702.             int n = match.Length;
  703.             if (n == 0)
  704.                 return null;
  705.             if (n == 1)
  706.                 return match[0] as PropertyInfo;
  707.             return (PropertyInfo)JSBinder.Select(typeRefs, match, n, argIRs, MemberTypes.Property);
  708.         }
  709.        
  710.         //Returns a value that quantifies the cost/badness of converting a value of type actual to type formal.
  711.         //Used to select the overload that is the closest match to the actual parameter.
  712.        
  713.         private static int TypeDistance(TypeReferences typeRefs, IReflect formal, IReflect actual)
  714.         {
  715.             if (formal is TypedArray) {
  716.                 if (actual is TypedArray) {
  717.                     TypedArray f = (TypedArray)formal;
  718.                     TypedArray a = (TypedArray)actual;
  719.                     if (f.rank == a.rank)
  720.                         return TypeDistance(typeRefs, f.elementType, a.elementType) == 0 ? 0 : 100;
  721.                 }
  722.                 else if (actual is Type) {
  723.                     TypedArray f = (TypedArray)formal;
  724.                     Type a = (Type)actual;
  725.                     if (a.IsArray && f.rank == a.GetArrayRank())
  726.                         return TypeDistance(typeRefs, f.elementType, a.GetElementType()) == 0 ? 0 : 100;
  727.                     else if (a == typeRefs.Array || a == typeRefs.ArrayObject)
  728.                         return 30;
  729.                 }
  730.                 return 100;
  731.             }
  732.             if (actual is TypedArray) {
  733.                 if (formal is Type) {
  734.                     Type f = (Type)formal;
  735.                     TypedArray a = (TypedArray)actual;
  736.                     if (f.IsArray && f.GetArrayRank() == a.rank)
  737.                         return TypeDistance(typeRefs, f.GetElementType(), a.elementType) == 0 ? 0 : 100;
  738.                     else if (f == typeRefs.Array)
  739.                         return 30;
  740.                     else if (f == typeRefs.Object)
  741.                         return 50;
  742.                 }
  743.                 return 100;
  744.             }
  745.             if (formal is ClassScope) {
  746.                 if (actual is ClassScope)
  747.                     return ((ClassScope)actual).IsSameOrDerivedFrom((ClassScope)formal) ? 0 : 100;
  748.                 else
  749.                     return 100;
  750.             }
  751.             if (actual is ClassScope) {
  752.                 if (formal is Type)
  753.                     return ((ClassScope)actual).IsPromotableTo((Type)formal) ? 0 : 100;
  754.                 else
  755.                     return 100;
  756.             }
  757.             return TypeDistance(typeRefs, Convert.ToType(typeRefs, formal), Convert.ToType(typeRefs, actual));
  758.         }
  759.        
  760.         private static int TypeDistance(TypeReferences typeRefs, Type formal, Type actual)
  761.         {
  762.             TypeCode atc = Type.GetTypeCode(actual);
  763.             TypeCode ftc = Type.GetTypeCode(formal);
  764.             if (actual.IsEnum)
  765.                 atc = TypeCode.Object;
  766.             if (formal.IsEnum)
  767.                 ftc = TypeCode.Object;
  768.             switch (atc) {
  769.                 case TypeCode.DBNull:
  770.                     switch (ftc) {
  771.                         default:
  772.                             return formal == typeRefs.Object ? 0 : 1;
  773.                     }
  774.                     break;
  775.                 case TypeCode.Boolean:
  776.                    
  777.                     switch (ftc) {
  778.                         case TypeCode.Boolean:
  779.                             return 0;
  780.                         case TypeCode.Byte:
  781.                             return 1;
  782.                         case TypeCode.UInt16:
  783.                             return 2;
  784.                         case TypeCode.UInt32:
  785.                             return 3;
  786.                         case TypeCode.UInt64:
  787.                             return 4;
  788.                         case TypeCode.SByte:
  789.                             return 5;
  790.                         case TypeCode.Int16:
  791.                             return 6;
  792.                         case TypeCode.Int32:
  793.                             return 7;
  794.                         case TypeCode.Int64:
  795.                             return 8;
  796.                         case TypeCode.Single:
  797.                             return 9;
  798.                         case TypeCode.Double:
  799.                             return 10;
  800.                         case TypeCode.Decimal:
  801.                             return 11;
  802.                         case TypeCode.Object:
  803.                             return TypeDistance(typeRefs, formal, actual, 12);
  804.                         case TypeCode.String:
  805.                             return 13;
  806.                         default:
  807.                             return 100;
  808.                     }
  809.                     break;
  810.                 case TypeCode.Char:
  811.                    
  812.                     switch (ftc) {
  813.                         case TypeCode.Char:
  814.                             return 0;
  815.                         case TypeCode.UInt16:
  816.                             return 1;
  817.                         case TypeCode.UInt32:
  818.                             return 2;
  819.                         case TypeCode.Int32:
  820.                             return 3;
  821.                         case TypeCode.UInt64:
  822.                             return 4;
  823.                         case TypeCode.Int64:
  824.                             return 5;
  825.                         case TypeCode.Single:
  826.                             return 6;
  827.                         case TypeCode.Double:
  828.                             return 7;
  829.                         case TypeCode.Decimal:
  830.                             return 8;
  831.                         case TypeCode.Object:
  832.                             return TypeDistance(typeRefs, formal, actual, 9);
  833.                         case TypeCode.String:
  834.                             return 10;
  835.                         case TypeCode.Int16:
  836.                             return 11;
  837.                         case TypeCode.Byte:
  838.                             return 12;
  839.                         case TypeCode.SByte:
  840.                             return 13;
  841.                         case TypeCode.Boolean:
  842.                             return 14;
  843.                         default:
  844.                             return 100;
  845.                     }
  846.                     break;
  847.                 case TypeCode.SByte:
  848.                    
  849.                     switch (ftc) {
  850.                         case TypeCode.SByte:
  851.                             return 0;
  852.                         case TypeCode.Int16:
  853.                             return 1;
  854.                         case TypeCode.Int32:
  855.                             return 2;
  856.                         case TypeCode.Int64:
  857.                             return 3;
  858.                         case TypeCode.Single:
  859.                             return 4;
  860.                         case TypeCode.Double:
  861.                             return 5;
  862.                         case TypeCode.Decimal:
  863.                             return 6;
  864.                         case TypeCode.Object:
  865.                             return TypeDistance(typeRefs, formal, actual, 7);
  866.                         case TypeCode.String:
  867.                             return 8;
  868.                         case TypeCode.Byte:
  869.                             return 9;
  870.                         case TypeCode.UInt16:
  871.                             return 10;
  872.                         case TypeCode.UInt32:
  873.                             return 12;
  874.                         case TypeCode.UInt64:
  875.                             return 13;
  876.                         case TypeCode.Boolean:
  877.                             return 14;
  878.                         default:
  879.                             return 100;
  880.                     }
  881.                     break;
  882.                 case TypeCode.Byte:
  883.                    
  884.                     switch (ftc) {
  885.                         case TypeCode.Byte:
  886.                             return 0;
  887.                         case TypeCode.UInt16:
  888.                             return 1;
  889.                         case TypeCode.Int16:
  890.                             return 3;
  891.                         case TypeCode.UInt32:
  892.                             return 4;
  893.                         case TypeCode.Int32:
  894.                             return 5;
  895.                         case TypeCode.UInt64:
  896.                             return 6;
  897.                         case TypeCode.Int64:
  898.                             return 7;
  899.                         case TypeCode.Single:
  900.                             return 8;
  901.                         case TypeCode.Double:
  902.                             return 9;
  903.                         case TypeCode.Decimal:
  904.                             return 10;
  905.                         case TypeCode.Object:
  906.                             return TypeDistance(typeRefs, formal, actual, 11);
  907.                         case TypeCode.String:
  908.                             return 12;
  909.                         case TypeCode.SByte:
  910.                             return 13;
  911.                         case TypeCode.Boolean:
  912.                             return 14;
  913.                         default:
  914.                             return 100;
  915.                     }
  916.                     break;
  917.                 case TypeCode.Int16:
  918.                    
  919.                     switch (ftc) {
  920.                         case TypeCode.Int16:
  921.                             return 0;
  922.                         case TypeCode.Int32:
  923.                             return 1;
  924.                         case TypeCode.Int64:
  925.                             return 2;
  926.                         case TypeCode.Single:
  927.                             return 3;
  928.                         case TypeCode.Double:
  929.                             return 4;
  930.                         case TypeCode.Decimal:
  931.                             return 5;
  932.                         case TypeCode.Object:
  933.                             return TypeDistance(typeRefs, formal, actual, 6);
  934.                         case TypeCode.String:
  935.                             return 7;
  936.                         case TypeCode.UInt16:
  937.                             return 8;
  938.                         case TypeCode.UInt32:
  939.                             return 10;
  940.                         case TypeCode.UInt64:
  941.                             return 11;
  942.                         case TypeCode.SByte:
  943.                             return 12;
  944.                         case TypeCode.Byte:
  945.                             return 13;
  946.                         case TypeCode.Boolean:
  947.                             return 14;
  948.                         default:
  949.                             return 100;
  950.                     }
  951.                     break;
  952.                 case TypeCode.UInt16:
  953.                    
  954.                     switch (ftc) {
  955.                         case TypeCode.UInt16:
  956.                             return 0;
  957.                         case TypeCode.UInt32:
  958.                             return 1;
  959.                         case TypeCode.UInt64:
  960.                             return 2;
  961.                         case TypeCode.Int32:
  962.                             return 4;
  963.                         case TypeCode.Int64:
  964.                             return 5;
  965.                         case TypeCode.Single:
  966.                             return 6;
  967.                         case TypeCode.Double:
  968.                             return 7;
  969.                         case TypeCode.Decimal:
  970.                             return 8;
  971.                         case TypeCode.Object:
  972.                             return TypeDistance(typeRefs, formal, actual, 9);
  973.                         case TypeCode.String:
  974.                             return 10;
  975.                         case TypeCode.Int16:
  976.                             return 11;
  977.                         case TypeCode.Byte:
  978.                             return 12;
  979.                         case TypeCode.SByte:
  980.                             return 13;
  981.                         case TypeCode.Boolean:
  982.                             return 14;
  983.                         default:
  984.                             return 100;
  985.                     }
  986.                     break;
  987.                 case TypeCode.Int32:
  988.                    
  989.                     switch (ftc) {
  990.                         case TypeCode.Int32:
  991.                             return 0;
  992.                         case TypeCode.Int64:
  993.                             return 1;
  994.                         case TypeCode.Double:
  995.                             return 2;
  996.                         case TypeCode.Decimal:
  997.                             return 3;
  998.                         case TypeCode.Object:
  999.                             return TypeDistance(typeRefs, formal, actual, 4);
  1000.                         case TypeCode.String:
  1001.                             return 5;
  1002.                         case TypeCode.UInt64:
  1003.                             return 6;
  1004.                         case TypeCode.UInt32:
  1005.                             return 7;
  1006.                         case TypeCode.Single:
  1007.                             return 8;
  1008.                         case TypeCode.Int16:
  1009.                             return 9;
  1010.                         case TypeCode.UInt16:
  1011.                             return 10;
  1012.                         case TypeCode.SByte:
  1013.                             return 12;
  1014.                         case TypeCode.Byte:
  1015.                             return 13;
  1016.                         case TypeCode.Boolean:
  1017.                             return 14;
  1018.                         default:
  1019.                             return 100;
  1020.                     }
  1021.                     break;
  1022.                 case TypeCode.UInt32:
  1023.                    
  1024.                     switch (ftc) {
  1025.                         case TypeCode.UInt32:
  1026.                             return 0;
  1027.                         case TypeCode.UInt64:
  1028.                             return 1;
  1029.                         case TypeCode.Int64:
  1030.                             return 2;
  1031.                         case TypeCode.Double:
  1032.                             return 3;
  1033.                         case TypeCode.Decimal:
  1034.                             return 4;
  1035.                         case TypeCode.Object:
  1036.                             return TypeDistance(typeRefs, formal, actual, 5);
  1037.                         case TypeCode.String:
  1038.                             return 6;
  1039.                         case TypeCode.Int32:
  1040.                             return 7;
  1041.                         case TypeCode.Single:
  1042.                             return 8;
  1043.                         case TypeCode.UInt16:
  1044.                             return 9;
  1045.                         case TypeCode.Int16:
  1046.                             return 11;
  1047.                         case TypeCode.Byte:
  1048.                             return 12;
  1049.                         case TypeCode.SByte:
  1050.                             return 13;
  1051.                         case TypeCode.Boolean:
  1052.                             return 14;
  1053.                         default:
  1054.                             return 100;
  1055.                     }
  1056.                     break;
  1057.                 case TypeCode.Int64:
  1058.                    
  1059.                     switch (ftc) {
  1060.                         case TypeCode.Int64:
  1061.                             return 0;
  1062.                         case TypeCode.Decimal:
  1063.                             return 1;
  1064.                         case TypeCode.Object:
  1065.                             return TypeDistance(typeRefs, formal, actual, 2);
  1066.                         case TypeCode.String:
  1067.                             return 3;
  1068.                         case TypeCode.Double:
  1069.                             return 4;
  1070.                         case TypeCode.Single:
  1071.                             return 5;
  1072.                         case TypeCode.Int32:
  1073.                             return 6;
  1074.                         case TypeCode.Int16:
  1075.                             return 7;
  1076.                         case TypeCode.SByte:
  1077.                             return 8;
  1078.                         case TypeCode.UInt64:
  1079.                             return 9;
  1080.                         case TypeCode.UInt32:
  1081.                             return 10;
  1082.                         case TypeCode.UInt16:
  1083.                             return 11;
  1084.                         case TypeCode.Byte:
  1085.                             return 13;
  1086.                         case TypeCode.Boolean:
  1087.                             return 14;
  1088.                         default:
  1089.                             return 100;
  1090.                     }
  1091.                     break;
  1092.                 case TypeCode.UInt64:
  1093.                    
  1094.                     switch (ftc) {
  1095.                         case TypeCode.UInt64:
  1096.                             return 0;
  1097.                         case TypeCode.Decimal:
  1098.                             return 1;
  1099.                         case TypeCode.Object:
  1100.                             return TypeDistance(typeRefs, formal, actual, 2);
  1101.                         case TypeCode.String:
  1102.                             return 3;
  1103.                         case TypeCode.Int64:
  1104.                             return 4;
  1105.                         case TypeCode.Double:
  1106.                             return 5;
  1107.                         case TypeCode.Single:
  1108.                             return 6;
  1109.                         case TypeCode.UInt32:
  1110.                             return 7;
  1111.                         case TypeCode.UInt16:
  1112.                             return 8;
  1113.                         case TypeCode.Byte:
  1114.                             return 10;
  1115.                         case TypeCode.Int32:
  1116.                             return 11;
  1117.                         case TypeCode.Int16:
  1118.                             return 12;
  1119.                         case TypeCode.SByte:
  1120.                             return 13;
  1121.                         case TypeCode.Boolean:
  1122.                             return 14;
  1123.                         default:
  1124.                             return 100;
  1125.                     }
  1126.                     break;
  1127.                 case TypeCode.Single:
  1128.                    
  1129.                     switch (ftc) {
  1130.                         case TypeCode.Single:
  1131.                             return 0;
  1132.                         case TypeCode.Double:
  1133.                             return 1;
  1134.                         case TypeCode.Decimal:
  1135.                             return 2;
  1136.                         case TypeCode.Int64:
  1137.                             return 3;
  1138.                         case TypeCode.UInt64:
  1139.                             return 4;
  1140.                         case TypeCode.Int32:
  1141.                             return 5;
  1142.                         case TypeCode.UInt32:
  1143.                             return 6;
  1144.                         case TypeCode.Int16:
  1145.                             return 7;
  1146.                         case TypeCode.UInt16:
  1147.                             return 8;
  1148.                         case TypeCode.SByte:
  1149.                             return 10;
  1150.                         case TypeCode.Byte:
  1151.                             return 11;
  1152.                         case TypeCode.Object:
  1153.                             return TypeDistance(typeRefs, formal, actual, 12);
  1154.                         case TypeCode.String:
  1155.                             return 13;
  1156.                         case TypeCode.Boolean:
  1157.                             return 14;
  1158.                         default:
  1159.                             return 100;
  1160.                     }
  1161.                     break;
  1162.                 case TypeCode.Double:
  1163.                    
  1164.                     switch (ftc) {
  1165.                         case TypeCode.Double:
  1166.                             return 0;
  1167.                         case TypeCode.Decimal:
  1168.                             return 1;
  1169.                         case TypeCode.Single:
  1170.                             return 2;
  1171.                         case TypeCode.Int64:
  1172.                             return 3;
  1173.                         case TypeCode.UInt64:
  1174.                             return 4;
  1175.                         case TypeCode.Int32:
  1176.                             return 5;
  1177.                         case TypeCode.UInt32:
  1178.                             return 6;
  1179.                         case TypeCode.Int16:
  1180.                             return 7;
  1181.                         case TypeCode.UInt16:
  1182.                             return 8;
  1183.                         case TypeCode.SByte:
  1184.                             return 10;
  1185.                         case TypeCode.Byte:
  1186.                             return 11;
  1187.                         case TypeCode.Object:
  1188.                             return TypeDistance(typeRefs, formal, actual, 12);
  1189.                         case TypeCode.String:
  1190.                             return 13;
  1191.                         case TypeCode.Boolean:
  1192.                             return 14;
  1193.                         default:
  1194.                             return 100;
  1195.                     }
  1196.                     break;
  1197.                 case TypeCode.Decimal:
  1198.                    
  1199.                     switch (ftc) {
  1200.                         case TypeCode.Decimal:
  1201.                             return 0;
  1202.                         case TypeCode.Double:
  1203.                             return 1;
  1204.                         case TypeCode.Single:
  1205.                             return 2;
  1206.                         case TypeCode.Int64:
  1207.                             return 3;
  1208.                         case TypeCode.UInt64:
  1209.                             return 4;
  1210.                         case TypeCode.Int32:
  1211.                             return 5;
  1212.                         case TypeCode.UInt32:
  1213.                             return 6;
  1214.                         case TypeCode.Int16:
  1215.                             return 7;
  1216.                         case TypeCode.UInt16:
  1217.                             return 8;
  1218.                         case TypeCode.SByte:
  1219.                             return 10;
  1220.                         case TypeCode.Byte:
  1221.                             return 11;
  1222.                         case TypeCode.Object:
  1223.                             return formal == typeRefs.Object ? 12 : 100;
  1224.                         case TypeCode.String:
  1225.                             return 13;
  1226.                         case TypeCode.Boolean:
  1227.                             return 14;
  1228.                         default:
  1229.                             return 100;
  1230.                     }
  1231.                     break;
  1232.                 case TypeCode.DateTime:
  1233.                    
  1234.                     switch (ftc) {
  1235.                         case TypeCode.DateTime:
  1236.                             return 0;
  1237.                         case TypeCode.Object:
  1238.                             return formal == typeRefs.Object ? 1 : 100;
  1239.                         case TypeCode.String:
  1240.                             return 3;
  1241.                         case TypeCode.Double:
  1242.                             return 4;
  1243.                         case TypeCode.Decimal:
  1244.                             return 5;
  1245.                         case TypeCode.UInt64:
  1246.                             return 6;
  1247.                         case TypeCode.Int64:
  1248.                             return 7;
  1249.                         case TypeCode.UInt32:
  1250.                             return 8;
  1251.                         case TypeCode.Int32:
  1252.                             return 9;
  1253.                         default:
  1254.                             return 100;
  1255.                     }
  1256.                     break;
  1257.                 case TypeCode.String:
  1258.                    
  1259.                     switch (ftc) {
  1260.                         case TypeCode.String:
  1261.                             return 0;
  1262.                         case TypeCode.Object:
  1263.                             return formal == typeRefs.Object ? 1 : 100;
  1264.                         case TypeCode.Char:
  1265.                             return 2;
  1266.                         default:
  1267.                             return 100;
  1268.                     }
  1269.                     break;
  1270.                 case TypeCode.Object:
  1271.                    
  1272.                     if (formal == actual)
  1273.                         return 0;
  1274.                     if (formal == typeRefs.Missing)
  1275.                         return 200;
  1276.                     if (!(formal.IsAssignableFrom(actual))) {
  1277.                         if (typeRefs.Array.IsAssignableFrom(formal) && (actual == typeRefs.Array || typeRefs.ArrayObject.IsAssignableFrom(actual)))
  1278.                             return 10;
  1279.                         else if (ftc == TypeCode.String)
  1280.                             return 20;
  1281.                         else if (actual == typeRefs.ScriptFunction && typeRefs.Delegate.IsAssignableFrom(formal))
  1282.                             return 19;
  1283.                         else
  1284.                             return 100;
  1285.                     }
  1286.                     Type[] interfaces = actual.GetInterfaces();
  1287.                     int i;
  1288.                     int n = interfaces.Length;
  1289.                     for (i = 0; i < n; i++)
  1290.                         if (formal == interfaces[i])
  1291.                             return i + 1;
  1292.                     for (i = 0; actual != typeRefs.Object && actual != null; i++) {
  1293.                         if (formal == actual)
  1294.                             return i + n + 1;
  1295.                         actual = actual.BaseType;
  1296.                     }
  1297.                     return i + n + 1;
  1298.             }
  1299.             return 0;
  1300.             //should never get here
  1301.         }
  1302.        
  1303.         private static int TypeDistance(TypeReferences typeRefs, Type formal, Type actual, int distFromObject)
  1304.         {
  1305.             if (formal == typeRefs.Object)
  1306.                 return distFromObject;
  1307.             if (formal.IsEnum)
  1308.                 return TypeDistance(typeRefs, Enum.GetUnderlyingType(formal), actual) + 10;
  1309.             return 100;
  1310.         }
  1311.     }
  1312. }

Developer Fusion