Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Remove new concurrent dictionary for generic method holders
  • Loading branch information
layomia authored and github-actions committed Oct 12, 2021
commit 830b179748a278cf79762fd7a7b5b73319375584
Original file line number Diff line number Diff line change
Expand Up @@ -600,9 +600,7 @@ internal JsonTypeInfo GetOrAddClass(Type type)
{
_haveTypesBeenCreated = true;

// todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes).
// https://github.com/dotnet/runtime/issues/32357
if (!_classes.TryGetValue(type, out JsonTypeInfo? result))
if (!TryGetClass(type, out JsonTypeInfo? result))
{
result = _classes.GetOrAdd(type, GetClassFromContextOrCreate(type));
}
Expand Down Expand Up @@ -644,6 +642,20 @@ internal JsonTypeInfo GetOrAddClassForRootType(Type type)
return jsonTypeInfo;
}

internal bool TryGetClass(Type type, [NotNullWhen(true)] out JsonTypeInfo? jsonTypeInfo)
{
// todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes).
// https://github.com/dotnet/runtime/issues/32357
if (!_classes.TryGetValue(type, out JsonTypeInfo? result))
{
jsonTypeInfo = null;
return false;
}

jsonTypeInfo = result;
return true;
}

internal bool TypeIsCached(Type type)
{
return _classes.ContainsKey(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ namespace System.Text.Json.Serialization.Metadata
/// </summary>
internal abstract class GenericMethodHolder
{
private static ConcurrentDictionary<Type, GenericMethodHolder>? s_holders;

/// <summary>
/// Returns the default value for the specified type.
/// </summary>
Expand All @@ -26,33 +24,12 @@ internal abstract class GenericMethodHolder
public abstract bool IsDefaultValue(object value);

/// <summary>
/// Returns a holder instance representing a type.
/// Creates a holder instance representing a type.
/// </summary>
public static GenericMethodHolder GetHolder(Type type)
public static GenericMethodHolder CreateHolder(Type type)
{
if (s_holders == null)
{
s_holders = new ConcurrentDictionary<Type, GenericMethodHolder>();
return CreateAndCacheHolder();
}
else
{
if (!s_holders.TryGetValue(type, out GenericMethodHolder? holder))
{
holder = CreateAndCacheHolder();
}

return holder;
}

GenericMethodHolder CreateAndCacheHolder()
{
Type holderType = typeof(GenericMethodHolder<>).MakeGenericType(type);
GenericMethodHolder holderInstance = (GenericMethodHolder)Activator.CreateInstance(holderType)!;
Debug.Assert(s_holders != null);
s_holders[type] = holderInstance;
return holderInstance;
}
Type holderType = typeof(GenericMethodHolder<>).MakeGenericType(type);
return (GenericMethodHolder)Activator.CreateInstance(holderType)!;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,18 @@ public static JsonParameterInfo CreateIgnoredParameterPlaceholder(
{
// The <T> value in the created JsonPropertyInfo<T> instance (sbyte)
// doesn't match the parameter type, use reflection to get the default value.
GenericMethodHolder holder = GenericMethodHolder.GetHolder(parameterInfo.ParameterType);
Type parameterType = parameterInfo.ParameterType;

GenericMethodHolder holder;
if (matchingProperty.Options.TryGetClass(parameterType, out JsonTypeInfo? typeInfo))
{
holder = typeInfo.GenericMethods;
}
else
{
holder = GenericMethodHolder.CreateHolder(parameterInfo.ParameterType);
}

jsonParameterInfo.DefaultValue = holder.DefaultValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ internal GenericMethodHolder GenericMethods
{
get
{
_genericMethods ??= GenericMethodHolder.GetHolder(Type);
_genericMethods ??= GenericMethodHolder.CreateHolder(Type);
return _genericMethods;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1307,5 +1307,20 @@ public class TypeWith_RefStringProp_ParamCtor

public TypeWith_RefStringProp_ParamCtor(ref string nameRef) => _name = nameRef;
}

[Fact]
public async Task BindToIgnoredPropOfSameType()
{
string json = @"{""Prop"":{}}";
Assert.NotNull(await JsonSerializerWrapperForString.DeserializeWrapper<ClassWithIgnoredSameType>(json));
}

public class ClassWithIgnoredSameType
{
[JsonIgnore]
public ClassWithIgnoredSameType Prop { get; }

public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ protected ConstructorTests_Metadata(JsonSerializerWrapperForString stringWrapper
[JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))]
[JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))]
[JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))]
[JsonSerializable(typeof(ClassWithIgnoredSameType))]
internal sealed partial class ConstructorTestsContext_Metadata : JsonSerializerContext
{
}
Expand Down Expand Up @@ -249,6 +250,7 @@ public ConstructorTests_Default()
[JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))]
[JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))]
[JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))]
[JsonSerializable(typeof(ClassWithIgnoredSameType))]
internal sealed partial class ConstructorTestsContext_Default : JsonSerializerContext
{
}
Expand Down