Skip to content

Commit df91ea5

Browse files
committed
Scope serializer caches to operations
1 parent 3fd5c09 commit df91ea5

11 files changed

+262
-173
lines changed

src/Tomlyn/Helpers/TomlNamingHelper.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/Tomlyn/Serialization/Internal/TomlPolymorphicTypeInfo.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ public override void Write(TomlWriter writer, object? value)
247247
throw new TomlException($"Type '{runtimeType.FullName}' is not registered as a derived type for '{Type.FullName}'.");
248248
}
249249

250-
var runtimeTypeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, runtimeType);
250+
var runtimeTypeInfo = writer.ResolveTypeInfo(runtimeType);
251251

252252
// Default derived type (null discriminator) - serialize without discriminator
253253
if (discriminator is null)
@@ -256,7 +256,7 @@ public override void Write(TomlWriter writer, object? value)
256256
return;
257257
}
258258

259-
var tempWriter = new TomlWriter(TextWriter.Null, Options);
259+
var tempWriter = new TomlWriter(TextWriter.Null, Options, writer.OperationState);
260260
tempWriter.WriteStartDocument();
261261
runtimeTypeInfo.Write(tempWriter, value);
262262

@@ -294,7 +294,7 @@ public override void Write(TomlWriter writer, object? value)
294294
// No discriminator found - try default derived type first
295295
if (_defaultDerivedType is not null)
296296
{
297-
var defaultTypeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, _defaultDerivedType);
297+
var defaultTypeInfo = reader.ResolveTypeInfo(_defaultDerivedType);
298298
var defaultReader = TomlReader.Create(buffer);
299299
defaultReader.Read(); // StartDocument
300300
defaultReader.Read(); // value start
@@ -323,12 +323,12 @@ public override void Write(TomlWriter writer, object? value)
323323

324324
if (_derivedTypeByDiscriminator.TryGetValue(discriminator, out var derivedType))
325325
{
326-
targetTypeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, derivedType);
326+
targetTypeInfo = reader.ResolveTypeInfo(derivedType);
327327
}
328328
else if (_defaultDerivedType is not null)
329329
{
330330
// Unknown discriminator - use default derived type
331-
targetTypeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, _defaultDerivedType);
331+
targetTypeInfo = reader.ResolveTypeInfo(_defaultDerivedType);
332332
}
333333
else if (_unknownDerivedTypeHandling == TomlUnknownDerivedTypeHandling.FallBackToBaseType && !Type.IsInterface && !Type.IsAbstract)
334334
{

src/Tomlyn/Serialization/Internal/TomlReflectionTypeInfoResolver.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ public override void Write(TomlWriter writer, object? value)
714714
}
715715
else
716716
{
717-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, member.MemberType);
717+
var typeInfo = writer.ResolveTypeInfo(member.MemberType);
718718
typeInfo.Write(writer, memberValue);
719719
}
720720
}
@@ -749,7 +749,7 @@ public override void Write(TomlWriter writer, object? value)
749749
}
750750
else
751751
{
752-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, _extensionDataValueType!);
752+
var typeInfo = writer.ResolveTypeInfo(_extensionDataValueType!);
753753
typeInfo.Write(writer, entry.Value);
754754
}
755755
}
@@ -914,7 +914,7 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
914914
return converter.Read(reader, member.MemberType);
915915
}
916916

917-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, member.MemberType);
917+
var typeInfo = reader.ResolveTypeInfo(member.MemberType);
918918
return typeInfo.ReadAsObject(reader);
919919
}
920920

@@ -950,7 +950,7 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
950950
}
951951
else
952952
{
953-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, member.MemberType);
953+
var typeInfo = reader.ResolveTypeInfo(member.MemberType);
954954
populatedValue = typeInfo.ReadInto(reader, existingValue);
955955
}
956956

@@ -985,7 +985,7 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
985985
return ReadMemberValue(reader, member);
986986
}
987987

988-
if (!TomlSingleOrArrayCollectionHelper.CanPopulate(member.MemberType, existingValue!))
988+
if (!reader.OperationState.SingleOrArrayCollections.CanPopulate(member.MemberType, existingValue!))
989989
{
990990
if (member.Setter is null)
991991
{
@@ -1001,7 +1001,7 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
10011001
return converter.Read(reader, member.MemberType);
10021002
}
10031003

1004-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, member.MemberType);
1004+
var typeInfo = reader.ResolveTypeInfo(member.MemberType);
10051005
var populatedValue = typeInfo.ReadInto(reader, existingValue);
10061006
if (member.Setter is null && !ReferenceEquals(existingValue, populatedValue))
10071007
{
@@ -1012,26 +1012,26 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
10121012
return populatedValue;
10131013
}
10141014

1015-
if (!TomlSingleOrArrayCollectionHelper.IsSupported(member.MemberType))
1015+
if (!reader.OperationState.SingleOrArrayCollections.IsSupported(member.MemberType))
10161016
{
10171017
throw reader.CreateException(
10181018
$"Member '{member.Member.Name}' on '{Type.FullName}' uses [TomlSingleOrArray] but '{member.MemberType.FullName}' is not a supported collection type.");
10191019
}
10201020

10211021
if (shouldPopulateExisting)
10221022
{
1023-
if (!TomlSingleOrArrayCollectionHelper.CanPopulate(member.MemberType, existingValue!))
1023+
if (!reader.OperationState.SingleOrArrayCollections.CanPopulate(member.MemberType, existingValue!))
10241024
{
10251025
if (member.Setter is null)
10261026
{
10271027
throw reader.CreateException(
10281028
$"Member '{member.Member.Name}' on '{Type.FullName}' uses [TomlSingleOrArray] but '{member.MemberType.FullName}' doesn't support populating the existing collection.");
10291029
}
10301030

1031-
return TomlSingleOrArrayCollectionHelper.ReadSingleElementAsCollection(reader, Options, member.MemberType);
1031+
return reader.OperationState.SingleOrArrayCollections.ReadSingleElementAsCollection(reader, member.MemberType);
10321032
}
10331033

1034-
return TomlSingleOrArrayCollectionHelper.ReadSingleElementIntoExisting(reader, Options, member.MemberType, existingValue!);
1034+
return reader.OperationState.SingleOrArrayCollections.ReadSingleElementIntoExisting(reader, member.MemberType, existingValue!);
10351035
}
10361036

10371037
if (member.Setter is null)
@@ -1040,7 +1040,7 @@ private object ReadIntoExistingInstance(TomlReader reader, object instance, Toml
10401040
$"Member '{member.Member.Name}' on '{Type.FullName}' uses [TomlSingleOrArray] but the existing collection is null or cannot be populated.");
10411041
}
10421042

1043-
return TomlSingleOrArrayCollectionHelper.ReadSingleElementAsCollection(reader, Options, member.MemberType);
1043+
return reader.OperationState.SingleOrArrayCollections.ReadSingleElementAsCollection(reader, member.MemberType);
10441044
}
10451045

10461046
private object CreateInstance()
@@ -1118,7 +1118,7 @@ private IDictionary CreateExtensionDataDictionary(Type memberType)
11181118
return TomlUntypedObjectConverter.ReadValue(reader);
11191119
}
11201120

1121-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, _extensionDataValueType!);
1121+
var typeInfo = reader.ResolveTypeInfo(_extensionDataValueType!);
11221122
return typeInfo.ReadAsObject(reader);
11231123
}
11241124

@@ -1173,7 +1173,7 @@ private object ReadWithConstructor(TomlReader reader, TomlSourceSpan? tableStart
11731173
}
11741174
else
11751175
{
1176-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, binding.ParameterType);
1176+
var typeInfo = reader.ResolveTypeInfo(binding.ParameterType);
11771177
value = typeInfo.ReadAsObject(reader);
11781178
}
11791179
ctorArgs[parameterIndex] = value;
@@ -1206,15 +1206,15 @@ private object ReadWithConstructor(TomlReader reader, TomlSourceSpan? tableStart
12061206
object? value;
12071207
if (member.HasSingleOrArray && reader.TokenType != TomlTokenType.StartArray)
12081208
{
1209-
value = TomlSingleOrArrayCollectionHelper.ReadSingleElementAsCollection(reader, Options, member.MemberType);
1209+
value = reader.OperationState.SingleOrArrayCollections.ReadSingleElementAsCollection(reader, member.MemberType);
12101210
}
12111211
else if (member.Converter is { } converter)
12121212
{
12131213
value = converter.Read(reader, member.MemberType);
12141214
}
12151215
else
12161216
{
1217-
var typeInfo = TomlTypeInfoResolverPipeline.Resolve(Options, member.MemberType);
1217+
var typeInfo = reader.ResolveTypeInfo(member.MemberType);
12181218
value = typeInfo.ReadAsObject(reader);
12191219
}
12201220
memberValues[memberIndex] = value;
@@ -1289,12 +1289,12 @@ private object ReadWithConstructor(TomlReader reader, TomlSourceSpan? tableStart
12891289
throw new TomlException($"Member '{member.Member.Name}' on '{Type.FullName}' uses [TomlSingleOrArray] but the existing collection is null or cannot be populated.");
12901290
}
12911291

1292-
if (!TomlSingleOrArrayCollectionHelper.CanPopulate(member.MemberType, existingValue))
1292+
if (!reader.OperationState.SingleOrArrayCollections.CanPopulate(member.MemberType, existingValue))
12931293
{
12941294
throw new TomlException($"Member '{member.Member.Name}' on '{Type.FullName}' uses [TomlSingleOrArray] but '{member.MemberType.FullName}' doesn't support populating the existing collection.");
12951295
}
12961296

1297-
TomlSingleOrArrayCollectionHelper.PopulateExistingFromCollection(member.MemberType, existingValue, memberValues[i]!);
1297+
reader.OperationState.SingleOrArrayCollections.PopulateExistingFromCollection(member.MemberType, existingValue, memberValues[i]!);
12981298
}
12991299

13001300
continue;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Alexandre Mutel. All rights reserved.
2+
// Licensed under the BSD-Clause 2 license.
3+
// See license.txt file in the project root for full license information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Diagnostics.CodeAnalysis;
8+
using Tomlyn.Helpers;
9+
10+
namespace Tomlyn.Serialization.Internal;
11+
12+
internal sealed class TomlSerializationOperationState
13+
{
14+
private readonly Dictionary<Type, TomlTypeInfo> _typeInfoCache = new();
15+
16+
public TomlSerializationOperationState(TomlSerializerOptions options)
17+
{
18+
ArgumentGuard.ThrowIfNull(options, nameof(options));
19+
20+
Options = options;
21+
SingleOrArrayCollections = new TomlSingleOrArrayCollectionHelper();
22+
}
23+
24+
public TomlSerializerOptions Options { get; }
25+
26+
public TomlSingleOrArrayCollectionHelper SingleOrArrayCollections { get; }
27+
28+
[RequiresUnreferencedCode(TomlTypeInfoResolverPipeline.ReflectionBasedSerializationMessage)]
29+
[RequiresDynamicCode(TomlTypeInfoResolverPipeline.ReflectionBasedSerializationMessage)]
30+
public TomlTypeInfo ResolveTypeInfo(Type type)
31+
{
32+
ArgumentGuard.ThrowIfNull(type, nameof(type));
33+
34+
return TomlTypeInfoResolverPipeline.Resolve(this, type);
35+
}
36+
37+
public bool TryGetCachedTypeInfo(Type type, [NotNullWhen(true)] out TomlTypeInfo? typeInfo)
38+
{
39+
ArgumentGuard.ThrowIfNull(type, nameof(type));
40+
return _typeInfoCache.TryGetValue(type, out typeInfo);
41+
}
42+
43+
public void CacheTypeInfo(Type type, TomlTypeInfo typeInfo)
44+
{
45+
ArgumentGuard.ThrowIfNull(type, nameof(type));
46+
ArgumentGuard.ThrowIfNull(typeInfo, nameof(typeInfo));
47+
_typeInfoCache[type] = typeInfo;
48+
}
49+
}

0 commit comments

Comments
 (0)