-Refactored JsonConverter creation
This commit is contained in:
@@ -7878,6 +7878,41 @@ Parameter name: value",
|
||||
}
|
||||
#endif
|
||||
|
||||
public class ErroringJsonConverter : JsonConverter
|
||||
{
|
||||
public ErroringJsonConverter(string s)
|
||||
{
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(ErroringJsonConverter))]
|
||||
public class ErroringTestClass
|
||||
{
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ErrorCreatingJsonConverter()
|
||||
{
|
||||
ExceptionAssert.Throws<JsonException>(
|
||||
"Error creating 'Newtonsoft.Json.Tests.Serialization.JsonSerializerTest+ErroringJsonConverter'.",
|
||||
() => JsonConvert.SerializeObject(new ErroringTestClass()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeInvalidOctalRootError()
|
||||
{
|
||||
|
||||
@@ -57,17 +57,5 @@ namespace Newtonsoft.Json
|
||||
|
||||
_converterType = converterType;
|
||||
}
|
||||
|
||||
internal static JsonConverter CreateJsonConverterInstance(Type converterType)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (JsonConverter)Activator.CreateInstance(converterType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonException("Error creating {0}".FormatWith(CultureInfo.InvariantCulture, converterType), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ namespace Newtonsoft.Json.Schema
|
||||
|
||||
private string GetTitle(Type type)
|
||||
{
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(type);
|
||||
|
||||
if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Title))
|
||||
return containerAttribute.Title;
|
||||
@@ -176,7 +176,7 @@ namespace Newtonsoft.Json.Schema
|
||||
|
||||
private string GetDescription(Type type)
|
||||
{
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(type);
|
||||
|
||||
if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Description))
|
||||
return containerAttribute.Description;
|
||||
@@ -192,7 +192,7 @@ namespace Newtonsoft.Json.Schema
|
||||
|
||||
private string GetTypeId(Type type, bool explicitOnly)
|
||||
{
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(type);
|
||||
|
||||
if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Id))
|
||||
return containerAttribute.Id;
|
||||
@@ -278,7 +278,7 @@ namespace Newtonsoft.Json.Schema
|
||||
|
||||
CurrentSchema.Id = GetTypeId(type, false);
|
||||
|
||||
JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
|
||||
JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetCachedAttribute<JsonArrayAttribute>(type);
|
||||
bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);
|
||||
|
||||
Type collectionItemType = ReflectionUtils.GetCollectionItemType(type);
|
||||
|
||||
@@ -371,7 +371,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute);
|
||||
contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization));
|
||||
|
||||
JsonObjectAttribute attribute = JsonTypeReflector.GetJsonObjectAttribute(contract.NonNullableUnderlyingType);
|
||||
JsonObjectAttribute attribute = JsonTypeReflector.GetCachedAttribute<JsonObjectAttribute>(contract.NonNullableUnderlyingType);
|
||||
if (attribute != null)
|
||||
contract.ItemRequired = attribute._itemRequired;
|
||||
|
||||
@@ -686,7 +686,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
#endif
|
||||
private void InitializeContract(JsonContract contract)
|
||||
{
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(contract.NonNullableUnderlyingType);
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(contract.NonNullableUnderlyingType);
|
||||
if (containerAttribute != null)
|
||||
{
|
||||
contract.IsReference = containerAttribute._isReference;
|
||||
@@ -963,18 +963,19 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <returns>A <see cref="JsonContract"/> for the given type.</returns>
|
||||
protected virtual JsonContract CreateContract(Type objectType)
|
||||
{
|
||||
Type t = ReflectionUtils.EnsureNotNullableType(objectType);
|
||||
|
||||
if (IsJsonPrimitiveType(objectType))
|
||||
return CreatePrimitiveContract(objectType);
|
||||
|
||||
if (JsonTypeReflector.GetJsonObjectAttribute(t) != null)
|
||||
Type t = ReflectionUtils.EnsureNotNullableType(objectType);
|
||||
JsonContainerAttribute containerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(t);
|
||||
|
||||
if (containerAttribute is JsonObjectAttribute)
|
||||
return CreateObjectContract(objectType);
|
||||
|
||||
if (JsonTypeReflector.GetJsonArrayAttribute(t) != null)
|
||||
if (containerAttribute is JsonArrayAttribute)
|
||||
return CreateArrayContract(objectType);
|
||||
|
||||
if (JsonTypeReflector.GetJsonDictionaryAttribute(t) != null)
|
||||
if (containerAttribute is JsonDictionaryAttribute)
|
||||
return CreateDictionaryContract(objectType);
|
||||
|
||||
if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken)))
|
||||
@@ -1268,7 +1269,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
property.ItemIsReference = (propertyAttribute != null) ? propertyAttribute._itemIsReference : null;
|
||||
property.ItemConverter =
|
||||
(propertyAttribute != null && propertyAttribute.ItemConverterType != null)
|
||||
? JsonConverterAttribute.CreateJsonConverterInstance(propertyAttribute.ItemConverterType)
|
||||
? JsonTypeReflector.CreateJsonConverterInstance(propertyAttribute.ItemConverterType)
|
||||
: null;
|
||||
property.ItemReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._itemReferenceLoopHandling : null;
|
||||
property.ItemTypeNameHandling = (propertyAttribute != null) ? propertyAttribute._itemTypeNameHandling : null;
|
||||
|
||||
@@ -100,12 +100,12 @@ namespace Newtonsoft.Json.Serialization
|
||||
internal JsonContainerContract(Type underlyingType)
|
||||
: base(underlyingType)
|
||||
{
|
||||
JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetJsonContainerAttribute(underlyingType);
|
||||
JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetCachedAttribute<JsonContainerAttribute>(underlyingType);
|
||||
|
||||
if (jsonContainerAttribute != null)
|
||||
{
|
||||
if (jsonContainerAttribute.ItemConverterType != null)
|
||||
ItemConverter = JsonConverterAttribute.CreateJsonConverterInstance(jsonContainerAttribute.ItemConverterType);
|
||||
ItemConverter = JsonTypeReflector.CreateJsonConverterInstance(jsonContainerAttribute.ItemConverterType);
|
||||
|
||||
ItemIsReference = jsonContainerAttribute._itemIsReference;
|
||||
ItemReferenceLoopHandling = jsonContainerAttribute._itemReferenceLoopHandling;
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace Newtonsoft.Json.Serialization
|
||||
public const string ShouldSerializePrefix = "ShouldSerialize";
|
||||
public const string SpecifiedPostfix = "Specified";
|
||||
|
||||
private static readonly ThreadSafeStore<object, Type> JsonConverterTypeCache = new ThreadSafeStore<object, Type>(GetJsonConverterTypeFromAttribute);
|
||||
private static readonly ThreadSafeStore<Type, Func<JsonConverter>> JsonConverterCreatorCache = new ThreadSafeStore<Type, Func<JsonConverter>>(GetJsonConverterCreator);
|
||||
|
||||
#if !(NET20 || NETFX_CORE)
|
||||
private static readonly ThreadSafeStore<Type, Type> AssociatedMetadataTypesCache = new ThreadSafeStore<Type, Type>(GetAssociateMetadataTypeFromAttribute);
|
||||
|
||||
@@ -65,33 +66,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
private static Type _cachedMetadataTypeAttributeType;
|
||||
#endif
|
||||
|
||||
public static JsonContainerAttribute GetJsonContainerAttribute(Type type)
|
||||
public static T GetCachedAttribute<T>(object attributeProvider) where T : Attribute
|
||||
{
|
||||
return CachedAttributeGetter<JsonContainerAttribute>.GetAttribute(type);
|
||||
return CachedAttributeGetter<T>.GetAttribute(attributeProvider);
|
||||
}
|
||||
|
||||
public static JsonObjectAttribute GetJsonObjectAttribute(Type type)
|
||||
{
|
||||
return GetJsonContainerAttribute(type) as JsonObjectAttribute;
|
||||
}
|
||||
|
||||
public static JsonArrayAttribute GetJsonArrayAttribute(Type type)
|
||||
{
|
||||
return GetJsonContainerAttribute(type) as JsonArrayAttribute;
|
||||
}
|
||||
|
||||
public static JsonDictionaryAttribute GetJsonDictionaryAttribute(Type type)
|
||||
{
|
||||
return GetJsonContainerAttribute(type) as JsonDictionaryAttribute;
|
||||
}
|
||||
|
||||
#if !(NETFX_CORE || PORTABLE || PORTABLE40)
|
||||
public static SerializableAttribute GetSerializableAttribute(Type type)
|
||||
{
|
||||
return CachedAttributeGetter<SerializableAttribute>.GetAttribute(type);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !NET20
|
||||
public static DataContractAttribute GetDataContractAttribute(Type type)
|
||||
{
|
||||
@@ -144,7 +123,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute)
|
||||
{
|
||||
JsonObjectAttribute objectAttribute = GetJsonObjectAttribute(objectType);
|
||||
JsonObjectAttribute objectAttribute = GetCachedAttribute<JsonObjectAttribute>(objectType);
|
||||
if (objectAttribute != null)
|
||||
return objectAttribute.MemberSerialization;
|
||||
|
||||
@@ -157,7 +136,7 @@ namespace Newtonsoft.Json.Serialization
|
||||
#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
|
||||
if (!ignoreSerializableAttribute)
|
||||
{
|
||||
SerializableAttribute serializableAttribute = GetSerializableAttribute(objectType);
|
||||
SerializableAttribute serializableAttribute = GetCachedAttribute<SerializableAttribute>(objectType);
|
||||
if (serializableAttribute != null)
|
||||
return MemberSerialization.Fields;
|
||||
}
|
||||
@@ -167,33 +146,48 @@ namespace Newtonsoft.Json.Serialization
|
||||
return MemberSerialization.OptOut;
|
||||
}
|
||||
|
||||
private static Type GetJsonConverterType(object attributeProvider)
|
||||
{
|
||||
return JsonConverterTypeCache.Get(attributeProvider);
|
||||
}
|
||||
|
||||
private static Type GetJsonConverterTypeFromAttribute(object attributeProvider)
|
||||
{
|
||||
JsonConverterAttribute converterAttribute = GetAttribute<JsonConverterAttribute>(attributeProvider);
|
||||
return (converterAttribute != null)
|
||||
? converterAttribute.ConverterType
|
||||
: null;
|
||||
}
|
||||
|
||||
public static JsonConverter GetJsonConverter(object attributeProvider)
|
||||
{
|
||||
Type converterType = GetJsonConverterType(attributeProvider);
|
||||
JsonConverterAttribute converterAttribute = GetCachedAttribute<JsonConverterAttribute>(attributeProvider);
|
||||
|
||||
if (converterType != null)
|
||||
if (converterAttribute != null)
|
||||
{
|
||||
JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
|
||||
|
||||
return memberConverter;
|
||||
Func<JsonConverter> creator = JsonConverterCreatorCache.Get(converterAttribute.ConverterType);
|
||||
if (creator != null)
|
||||
return creator();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JsonConverter CreateJsonConverterInstance(Type converterType)
|
||||
{
|
||||
Func<JsonConverter> converterCreator = JsonConverterCreatorCache.Get(converterType);
|
||||
return converterCreator();
|
||||
}
|
||||
|
||||
private static Func<JsonConverter> GetJsonConverterCreator(Type converterType)
|
||||
{
|
||||
Func<object> defaultConstructor = (ReflectionUtils.HasDefaultConstructor(converterType, false))
|
||||
? ReflectionDelegateFactory.CreateDefaultConstructor<object>(converterType)
|
||||
: null;
|
||||
|
||||
return () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (defaultConstructor == null)
|
||||
throw new JsonException("No parameterless constructor defined for '{0}'.".FormatWith(CultureInfo.InvariantCulture, converterType));
|
||||
|
||||
return (JsonConverter)defaultConstructor();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new JsonException("Error creating '{0}'.".FormatWith(CultureInfo.InvariantCulture, converterType), ex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
|
||||
public static TypeConverter GetTypeConverter(Type type)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user