<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />

MethodBinder

static class MethodBinder
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Newtonsoft.Json.Utilities { internal static class MethodBinder { private class ParametersMatchComparer : IComparer<ParameterInfo[]> { private readonly IList<Type> _types; private readonly bool _enableParamArray; public ParametersMatchComparer(IList<Type> types, bool enableParamArray) { ValidationUtils.ArgumentNotNull(types, "types"); _types = types; _enableParamArray = enableParamArray; } public int Compare(ParameterInfo[] parameters1, ParameterInfo[] parameters2) { ValidationUtils.ArgumentNotNull(parameters1, "parameters1"); ValidationUtils.ArgumentNotNull(parameters2, "parameters2"); if (parameters1.Length == 0) return -1; if (parameters2.Length == 0) return 1; Type type = null; Type type2 = null; if (_enableParamArray) { ParameterInfo parameterInfo = parameters1[parameters1.Length - 1]; if (parameterInfo.ParameterType.IsArray && CustomAttributeExtensions.IsDefined(parameterInfo, typeof(ParamArrayAttribute))) type = parameterInfo.ParameterType.GetElementType(); ParameterInfo parameterInfo2 = parameters2[parameters2.Length - 1]; if (parameterInfo2.ParameterType.IsArray && CustomAttributeExtensions.IsDefined(parameterInfo2, typeof(ParamArrayAttribute))) type2 = parameterInfo2.ParameterType.GetElementType(); if ((object)type != null && (object)type2 == null) return 1; if ((object)type2 != null && (object)type == null) return -1; } for (int i = 0; i < _types.Count; i++) { Type type3 = ((object)type != null && i >= parameters1.Length - 1) ? type : parameters1[i].ParameterType; Type type4 = ((object)type2 != null && i >= parameters2.Length - 1) ? type2 : parameters2[i].ParameterType; if ((object)type3 != type4) { if ((object)type3 == _types[i]) return -1; if ((object)type4 == _types[i]) return 1; int num = ChooseMorePreciseType(type3, type4); if (num != 0) return num; } } return 0; } private static int ChooseMorePreciseType(Type type1, Type type2) { if (type1.IsByRef || type2.IsByRef) { if (type1.IsByRef && type2.IsByRef) { type1 = type1.GetElementType(); type2 = type2.GetElementType(); } else if (type1.IsByRef) { type1 = type1.GetElementType(); if ((object)type1 == type2) return 1; } else { type2 = type2.GetElementType(); if ((object)type2 == type1) return -1; } } bool flag; bool flag2; if (type1.IsPrimitive() && type2.IsPrimitive()) { flag = CanConvertPrimitive(type2, type1); flag2 = CanConvertPrimitive(type1, type2); } else { flag = TypeExtensions.IsAssignableFrom(type1, type2); flag2 = TypeExtensions.IsAssignableFrom(type2, type1); } if (flag == flag2) return 0; if (!flag) return -1; return 1; } } private static readonly Type[] PrimitiveTypes = new Type[12] { typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double) }; private static readonly int[] WideningMasks = new int[12] { 1, 4066, 3412, 4090, 3408, 4066, 3392, 3968, 3328, 3584, 3072, 2048 }; private static bool CanConvertPrimitive(Type from, Type to) { if ((object)from == to) return true; int num = 0; int num2 = 0; for (int i = 0; i < PrimitiveTypes.Length; i++) { if ((object)PrimitiveTypes[i] == from) num = WideningMasks[i]; else if ((object)PrimitiveTypes[i] == to) { num2 = 1 << i; } if (num != 0 && num2 != 0) break; } return (num & num2) != 0; } private static bool FilterParameters(ParameterInfo[] parameters, IList<Type> types, bool enableParamArray) { ValidationUtils.ArgumentNotNull(parameters, "parameters"); ValidationUtils.ArgumentNotNull(types, "types"); if (parameters.Length == 0) return types.Count == 0; if (parameters.Length > types.Count) return false; Type type = null; if (enableParamArray) { ParameterInfo parameterInfo = parameters[parameters.Length - 1]; if (parameterInfo.ParameterType.IsArray && CustomAttributeExtensions.IsDefined(parameterInfo, typeof(ParamArrayAttribute))) type = parameterInfo.ParameterType.GetElementType(); } if ((object)type == null && parameters.Length != types.Count) return false; for (int i = 0; i < types.Count; i++) { Type type2 = ((object)type != null && i >= parameters.Length - 1) ? type : parameters[i].ParameterType; if ((object)type2 != types[i] && (object)type2 != typeof(object)) { if (type2.IsPrimitive()) { if (!types[i].IsPrimitive() || !CanConvertPrimitive(types[i], type2)) return false; } else if (!TypeExtensions.IsAssignableFrom(type2, types[i])) { return false; } } } return true; } public static TMethod SelectMethod<TMethod>(IEnumerable<TMethod> candidates, IList<Type> types) where TMethod : MethodBase { ValidationUtils.ArgumentNotNull(candidates, "candidates"); ValidationUtils.ArgumentNotNull(types, "types"); return (from m in candidates where FilterParameters(m.GetParameters(), types, false) select m).OrderBy((TMethod m) => m.GetParameters(), new ParametersMatchComparer(types, false)).FirstOrDefault(); } } }