Advanced constructor parameter binding on .NET Core & portable
This commit is contained in:
@@ -1330,6 +1330,310 @@ namespace Newtonsoft.Json.Tests
|
||||
public string One { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class OverloadsJsonConverterer : JsonConverter
|
||||
{
|
||||
private readonly string _type;
|
||||
|
||||
// constructor with Type argument
|
||||
|
||||
public OverloadsJsonConverterer(Type typeParam)
|
||||
{
|
||||
_type = "Type";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(object objectParam)
|
||||
{
|
||||
_type = string.Format("object({0})", objectParam.GetType().FullName);
|
||||
}
|
||||
|
||||
// primitive type conversions
|
||||
|
||||
public OverloadsJsonConverterer(byte byteParam)
|
||||
{
|
||||
_type = "byte";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(short shortParam)
|
||||
{
|
||||
_type = "short";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(int intParam)
|
||||
{
|
||||
_type = "int";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(long longParam)
|
||||
{
|
||||
_type = "long";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(double doubleParam)
|
||||
{
|
||||
_type = "double";
|
||||
}
|
||||
|
||||
// params argument
|
||||
|
||||
public OverloadsJsonConverterer(params int[] intParams)
|
||||
{
|
||||
_type = "int[]";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(bool[] intParams)
|
||||
{
|
||||
_type = "bool[]";
|
||||
}
|
||||
|
||||
// closest type resolution
|
||||
|
||||
public OverloadsJsonConverterer(IEnumerable<string> iEnumerableParam)
|
||||
{
|
||||
_type = "IEnumerable<string>";
|
||||
}
|
||||
|
||||
public OverloadsJsonConverterer(IList<string> iListParam)
|
||||
{
|
||||
_type = "IList<string>";
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(_type);
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
return objectType == typeof(int);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class OverloadWithTypeParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), typeof(int))]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonConverterConstructor_OverloadWithTypeParam()
|
||||
{
|
||||
OverloadWithTypeParameter value = new OverloadWithTypeParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
|
||||
Assert.AreEqual("{\"Overload\":\"Type\"}", json);
|
||||
}
|
||||
|
||||
public class OverloadWithUnhandledParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), "str")]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonConverterConstructor_OverloadWithUnhandledParam_FallbackToObject()
|
||||
{
|
||||
OverloadWithUnhandledParameter value = new OverloadWithUnhandledParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
|
||||
Assert.AreEqual("{\"Overload\":\"object(System.String)\"}", json);
|
||||
}
|
||||
|
||||
public class OverloadWithIntParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithUIntParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1U)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithLongParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1L)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithULongParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1UL)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithShortParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), (short)1)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithUShortParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), (ushort)1)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithSByteParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), (sbyte)1)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithByteParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), (byte)1)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithCharParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 'a')]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithBoolParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), true)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithFloatParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1.5f)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
public class OverloadWithDoubleParameter
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), 1.5)]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonConverterConstructor_OverloadsWithPrimitiveParams()
|
||||
{
|
||||
{
|
||||
OverloadWithIntParameter value = new OverloadWithIntParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"int\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// uint -> long
|
||||
OverloadWithUIntParameter value = new OverloadWithUIntParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"long\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
OverloadWithLongParameter value = new OverloadWithLongParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"long\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// ulong -> double
|
||||
OverloadWithULongParameter value = new OverloadWithULongParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"double\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
OverloadWithShortParameter value = new OverloadWithShortParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"short\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// ushort -> int
|
||||
OverloadWithUShortParameter value = new OverloadWithUShortParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"int\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// sbyte -> short
|
||||
OverloadWithSByteParameter value = new OverloadWithSByteParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"short\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
OverloadWithByteParameter value = new OverloadWithByteParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"byte\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// char -> int
|
||||
OverloadWithCharParameter value = new OverloadWithCharParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"int\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// bool -> (object)bool
|
||||
OverloadWithBoolParameter value = new OverloadWithBoolParameter();
|
||||
var json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"object(System.Boolean)\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
// float -> double
|
||||
OverloadWithFloatParameter value = new OverloadWithFloatParameter();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"double\"}", json);
|
||||
}
|
||||
|
||||
{
|
||||
OverloadWithDoubleParameter value = new OverloadWithDoubleParameter();
|
||||
var json = JsonConvert.SerializeObject(value);
|
||||
Assert.AreEqual("{\"Overload\":\"double\"}", json);
|
||||
}
|
||||
}
|
||||
|
||||
public class OverloadWithArrayParameters
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), new int[] { 1, 2, 3 })]
|
||||
public int WithParams { get; set; }
|
||||
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), new bool[] { true, false })]
|
||||
public int WithoutParams { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonConverterConstructor_OverloadsWithArrayParams()
|
||||
{
|
||||
OverloadWithArrayParameters value = new OverloadWithArrayParameters();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
|
||||
Assert.AreEqual("{\"WithParams\":\"int[]\",\"WithoutParams\":\"bool[]\"}", json);
|
||||
}
|
||||
|
||||
public class OverloadWithBaseType
|
||||
{
|
||||
[JsonConverter(typeof(OverloadsJsonConverterer), new object[] { new string[] { "a", "b", "c" } })]
|
||||
public int Overload { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JsonConverterConstructor_OverloadsWithBaseTypes()
|
||||
{
|
||||
OverloadWithBaseType value = new OverloadWithBaseType();
|
||||
string json = JsonConvert.SerializeObject(value);
|
||||
|
||||
Assert.AreEqual("{\"Overload\":\"IList<string>\"}", json);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void CustomDoubleRounding()
|
||||
{
|
||||
|
||||
@@ -163,6 +163,20 @@ namespace Newtonsoft.Json.Utilities
|
||||
// parameter has value, get value from array again and unbox
|
||||
generator.MarkLabel(skipSettingDefault);
|
||||
generator.PushArrayInstance(argsIndex, i);
|
||||
|
||||
if (parameterType.IsPrimitive())
|
||||
{
|
||||
// for primitive types we need to call Convert.ChangeType() to correctly
|
||||
// convert value from other compatible primitive types (e.g. short -> int)
|
||||
|
||||
generator.Emit(OpCodes.Ldtoken, parameterType);
|
||||
generator.Emit(OpCodes.Call, typeof(Type).GetMethod(
|
||||
"GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }));
|
||||
|
||||
generator.Emit(OpCodes.Call, typeof(Convert).GetMethod(
|
||||
"ChangeType", new[] { typeof(object), typeof(Type) }));
|
||||
}
|
||||
|
||||
generator.UnboxIfNeeded(parameterType);
|
||||
|
||||
// parameter finished, we out!
|
||||
|
||||
@@ -360,6 +360,13 @@ namespace Newtonsoft.Json.Utilities
|
||||
return expression;
|
||||
}
|
||||
|
||||
if (targetType.IsPrimitive())
|
||||
{
|
||||
expression = Expression.Call(
|
||||
typeof(Convert).GetMethod("ChangeType", new[] { typeof(object), typeof(Type) }),
|
||||
expression, Expression.Constant(targetType));
|
||||
}
|
||||
|
||||
return Expression.Convert(expression, targetType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,226 @@ namespace Newtonsoft.Json.Utilities
|
||||
}
|
||||
|
||||
#if !DOTNET
|
||||
|
||||
private static readonly Type[] PrimitiveTypes = new Type[]
|
||||
{
|
||||
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[]
|
||||
{
|
||||
0x0001, 0x0FE2, 0x0D54, 0x0FFA,
|
||||
0x0D50, 0x0FE2, 0x0D40, 0x0F80,
|
||||
0x0D00, 0x0E00, 0x0C00, 0x0800
|
||||
};
|
||||
|
||||
internal static bool CanConvertPrimitive(Type from, Type to)
|
||||
{
|
||||
if (from == to) return true;
|
||||
|
||||
int fromMask = 0, toMask = 0;
|
||||
|
||||
for (int i = 0; i < PrimitiveTypes.Length && (fromMask == 0 || toMask == 0); i++)
|
||||
{
|
||||
if (PrimitiveTypes[i] == from)
|
||||
{
|
||||
fromMask = WideningMasks[i];
|
||||
}
|
||||
else if (PrimitiveTypes[i] == to)
|
||||
{
|
||||
toMask = 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
return (fromMask & toMask) != 0;
|
||||
}
|
||||
|
||||
private static bool FilterParameters(ParameterInfo[] parameters, IList<Type> types, bool enableParamArray)
|
||||
{
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException(nameof(parameters));
|
||||
if (types == null)
|
||||
throw new ArgumentNullException(nameof(types));
|
||||
|
||||
if (parameters.Length == 0)
|
||||
{
|
||||
// fast check for parameterless methods
|
||||
return types.Count == 0;
|
||||
}
|
||||
|
||||
if (parameters.Length > types.Count)
|
||||
{
|
||||
// not all declared parameters were specified (optional parameters are not supported)
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if the last parameter is ParamArray
|
||||
Type paramArrayType = null;
|
||||
|
||||
if (enableParamArray &&
|
||||
parameters[parameters.Length - 1].ParameterType.IsArray &&
|
||||
parameters[parameters.Length - 1].IsDefined(typeof(ParamArrayAttribute)))
|
||||
{
|
||||
paramArrayType = parameters[parameters.Length - 1].ParameterType.GetElementType();
|
||||
}
|
||||
|
||||
if (paramArrayType == null && parameters.Length != types.Count)
|
||||
{
|
||||
// when there's no ParamArray, number of parameters should match
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < types.Count; i++)
|
||||
{
|
||||
var paramType = (paramArrayType != null && i >= parameters.Length - 1) ? paramArrayType : parameters[i].ParameterType;
|
||||
|
||||
// exact match with provided type
|
||||
if (paramType == types[i]) continue;
|
||||
|
||||
// parameter of type object matches anything
|
||||
if (paramType == typeof(object)) continue;
|
||||
|
||||
if (paramType.IsPrimitive())
|
||||
{
|
||||
// primitive parameter can only be assigned from compatible primitive type
|
||||
if (!types[i].IsPrimitive() || !CanConvertPrimitive(types[i], paramType))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!paramType.IsAssignableFrom(types[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class ParametersMatchComparer : IComparer<ParameterInfo[]>
|
||||
{
|
||||
private readonly IList<Type> _types;
|
||||
private readonly bool _enableParamArray;
|
||||
|
||||
public ParametersMatchComparer(IList<Type> types, bool enableParamArray)
|
||||
{
|
||||
if (types == null)
|
||||
throw new ArgumentNullException(nameof(types));
|
||||
|
||||
_types = types;
|
||||
_enableParamArray = enableParamArray;
|
||||
}
|
||||
|
||||
public int Compare(ParameterInfo[] parameters1, ParameterInfo[] parameters2)
|
||||
{
|
||||
if (parameters1 == null)
|
||||
throw new ArgumentNullException(nameof(parameters1));
|
||||
if (parameters2 == null)
|
||||
throw new ArgumentNullException(nameof(parameters2));
|
||||
|
||||
// parameterless method wins
|
||||
if (parameters1.Length == 0) return -1;
|
||||
if (parameters2.Length == 0) return 1;
|
||||
|
||||
Type paramArrayType1 = null, paramArrayType2 = null;
|
||||
|
||||
if (_enableParamArray)
|
||||
{
|
||||
if (parameters1[parameters1.Length - 1].ParameterType.IsArray &&
|
||||
parameters1[parameters1.Length - 1].IsDefined(typeof(ParamArrayAttribute)))
|
||||
{
|
||||
paramArrayType1 = parameters1[parameters1.Length - 1].ParameterType.GetElementType();
|
||||
}
|
||||
|
||||
if (parameters2[parameters2.Length - 1].ParameterType.IsArray &&
|
||||
parameters2[parameters2.Length - 1].IsDefined(typeof(ParamArrayAttribute)))
|
||||
{
|
||||
paramArrayType2 = parameters2[parameters2.Length - 1].ParameterType.GetElementType();
|
||||
}
|
||||
|
||||
// A method using params always loses to one not using params
|
||||
if (paramArrayType1 != null && paramArrayType2 == null) return 1;
|
||||
if (paramArrayType2 != null && paramArrayType1 == null) return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _types.Count; i++)
|
||||
{
|
||||
var type1 = (paramArrayType1 != null && i >= parameters1.Length - 1) ? paramArrayType1 : parameters1[i].ParameterType;
|
||||
var type2 = (paramArrayType2 != null && i >= parameters2.Length - 1) ? paramArrayType2 : parameters2[i].ParameterType;
|
||||
|
||||
// exact match between parameter types doesn't change score
|
||||
if (type1 == type2) continue;
|
||||
|
||||
// exact match with source type decides winner immediately
|
||||
if (type1 == _types[i]) return -1;
|
||||
if (type2 == _types[i]) return 1;
|
||||
|
||||
var r = ChooseMorePreciseType(type1, type2);
|
||||
if (r != 0) return r;
|
||||
}
|
||||
|
||||
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 (type1 == type2) return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
type2 = type2.GetElementType();
|
||||
if (type2 == type1) return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool c1FromC2, c2FromC1;
|
||||
|
||||
if (type1.IsPrimitive() && type2.IsPrimitive())
|
||||
{
|
||||
c1FromC2 = CanConvertPrimitive(type2, type1);
|
||||
c2FromC1 = CanConvertPrimitive(type1, type2);
|
||||
}
|
||||
else
|
||||
{
|
||||
c1FromC2 = type1.IsAssignableFrom(type2);
|
||||
c2FromC1 = type2.IsAssignableFrom(type1);
|
||||
}
|
||||
|
||||
if (c1FromC2 == c2FromC1) return 0;
|
||||
|
||||
return c1FromC2 ? 1 : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static MethodBase SelectMethod(IEnumerable<MethodBase> candidates, BindingFlags bindingFlags, IList<Type> types)
|
||||
{
|
||||
if (candidates == null)
|
||||
throw new ArgumentNullException(nameof(candidates));
|
||||
if (types == null)
|
||||
throw new ArgumentNullException(nameof(types));
|
||||
|
||||
// ParamArrays are not supported by ReflectionDelegateFactory
|
||||
// They will be treated like ordinary array arguments
|
||||
const bool enableParamArray = false;
|
||||
|
||||
return candidates
|
||||
.Where(m => TestAccessibility(m, bindingFlags) && FilterParameters(m.GetParameters(), types, enableParamArray))
|
||||
.OrderBy(m => m.GetParameters(), new ParametersMatchComparer(types, enableParamArray))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, string name)
|
||||
{
|
||||
return type.GetMethod(name, DefaultFlags);
|
||||
@@ -295,21 +515,7 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags, object placeHolder1, IList<Type> parameterTypes, object placeHolder2)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredMethods.Where(
|
||||
m =>
|
||||
{
|
||||
if (name != null && m.Name != name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TestAccessibility(m, bindingFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes);
|
||||
}).SingleOrDefault();
|
||||
return (MethodInfo)SelectMethod(type.GetTypeInfo().DeclaredMethods.Where(m => name == null || m.Name == name), bindingFlags, parameterTypes);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConstructorInfo> GetConstructors(this Type type)
|
||||
@@ -319,28 +525,9 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags)
|
||||
{
|
||||
return type.GetConstructors(bindingFlags, null);
|
||||
return type.GetTypeInfo().DeclaredConstructors.Where(c => TestAccessibility(c, bindingFlags));
|
||||
}
|
||||
|
||||
private static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetTypeInfo().DeclaredConstructors.Where(
|
||||
c =>
|
||||
{
|
||||
if (!TestAccessibility(c, bindingFlags))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameterTypes != null && !c.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static ConstructorInfo GetConstructor(this Type type, IList<Type> parameterTypes)
|
||||
{
|
||||
return type.GetConstructor(DefaultFlags, null, parameterTypes, null);
|
||||
@@ -348,9 +535,9 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object placeholder1, IList<Type> parameterTypes, object placeholder2)
|
||||
{
|
||||
return type.GetConstructors(bindingFlags, parameterTypes).SingleOrDefault();
|
||||
return (ConstructorInfo)SelectMethod(type.GetTypeInfo().DeclaredConstructors, bindingFlags, parameterTypes);
|
||||
}
|
||||
|
||||
|
||||
public static MemberInfo[] GetMember(this Type type, string member)
|
||||
{
|
||||
return type.GetMemberInternal(member, null, DefaultFlags);
|
||||
@@ -573,6 +760,15 @@ namespace Newtonsoft.Json.Utilities
|
||||
return type.GetTypeInfo().IsValueType;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool IsPrimitive(this Type type)
|
||||
{
|
||||
#if !(DOTNET || PORTABLE)
|
||||
return type.IsPrimitive;
|
||||
#else
|
||||
return type.GetTypeInfo().IsPrimitive;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool AssignableToTypeName(this Type type, string fullTypeName, out Type match)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user