Skip to content

Commit

Permalink
Move unique attribute resolution logic to reflection extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
eiriktsarpalis committed Jul 1, 2022
1 parent dfec188 commit 2b03985
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 44 deletions.
19 changes: 19 additions & 0 deletions src/libraries/System.Text.Json/src/System/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,24 @@ public static bool IsAssignableFromInternal(this Type type, Type from)

private static bool HasJsonConstructorAttribute(ConstructorInfo constructorInfo)
=> constructorInfo.GetCustomAttribute<JsonConstructorAttribute>() != null;

public static TAttribute? GetUniqueCustomAttribute<TAttribute>(this MemberInfo memberInfo, bool inherit)
where TAttribute : Attribute
{
object[] attributes = memberInfo.GetCustomAttributes(typeof(TAttribute), inherit);

if (attributes.Length == 0)
{
return null;
}

if (attributes.Length == 1)
{
return (TAttribute)attributes[0];
}

ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(typeof(TAttribute), memberInfo);
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ public sealed partial class JsonSerializerOptions
Debug.Assert(memberInfo.DeclaringType != null, "Properties and fields always have a declaring type.");
JsonConverter? converter = null;

JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?)
GetAttributeThatCanHaveMultiple(memberInfo.DeclaringType, typeof(JsonConverterAttribute), memberInfo);

JsonConverterAttribute? converterAttribute = memberInfo.GetUniqueCustomAttribute<JsonConverterAttribute>(inherit: false);
if (converterAttribute != null)
{
converter = GetConverterFromAttribute(converterAttribute, typeToConvert, memberInfo);
Expand Down Expand Up @@ -176,9 +174,7 @@ private JsonConverter GetConverterFromOptionsOrReflectionConverter(Type typeToCo
// Priority 2: Attempt to get converter from [JsonConverter] on the type being converted.
if (converter == null)
{
JsonConverterAttribute? converterAttribute = (JsonConverterAttribute?)
GetAttributeThatCanHaveMultiple(typeToConvert, typeof(JsonConverterAttribute));

JsonConverterAttribute? converterAttribute = typeToConvert.GetUniqueCustomAttribute<JsonConverterAttribute>(inherit: false);
if (converterAttribute != null)
{
converter = GetConverterFromAttribute(converterAttribute, typeToConvert: typeToConvert, memberInfo: null);
Expand Down Expand Up @@ -257,33 +253,5 @@ private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converter

return converter;
}

private static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType, MemberInfo memberInfo)
{
object[] attributes = memberInfo.GetCustomAttributes(attributeType, inherit: false);
return GetAttributeThatCanHaveMultiple(attributeType, classType, memberInfo, attributes);
}

internal static Attribute? GetAttributeThatCanHaveMultiple(Type classType, Type attributeType)
{
object[] attributes = classType.GetCustomAttributes(attributeType, inherit: false);
return GetAttributeThatCanHaveMultiple(attributeType, classType, null, attributes);
}

private static Attribute? GetAttributeThatCanHaveMultiple(Type attributeType, Type classType, MemberInfo? memberInfo, object[] attributes)
{
if (attributes.Length == 0)
{
return null;
}

if (attributes.Length == 1)
{
return (Attribute)attributes[0];
}

ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(attributeType, classType, memberInfo);
return default;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,7 @@ private void CacheMember(

private static JsonNumberHandling? GetNumberHandlingForType(Type type)
{
var numberHandlingAttribute =
(JsonNumberHandlingAttribute?)JsonSerializerOptions.GetAttributeThatCanHaveMultiple(type, typeof(JsonNumberHandlingAttribute));

JsonNumberHandlingAttribute? numberHandlingAttribute = type.GetUniqueCustomAttribute<JsonNumberHandlingAttribute>(inherit: false);
return numberHandlingAttribute?.Handling;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,14 +398,9 @@ public static void AddJsonExceptionInformation(ref WriteStack state, JsonExcepti
}

[DoesNotReturn]
public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, Type classType, MemberInfo? memberInfo)
public static void ThrowInvalidOperationException_SerializationDuplicateAttribute(Type attribute, MemberInfo memberInfo)
{
string location = classType.ToString();
if (memberInfo != null)
{
location += $".{memberInfo.Name}";
}

string location = memberInfo is Type type ? type.ToString() : $"{memberInfo.DeclaringType}.{memberInfo.Name}";
throw new InvalidOperationException(SR.Format(SR.SerializationDuplicateAttribute, attribute, location));
}

Expand Down

0 comments on commit 2b03985

Please sign in to comment.