Refactor JSON/Binary context & metadata class structure
Renamed and split internal context and metadata classes for JSON and binary serialization/deserialization. - Replaced CrossTypeDeserializerBase with DeserializeCrossTypeBase; updated all usages. - Renamed DeserializationContextPool to JsonDeserializationContextPool; SerializationContextPool now uses JsonSerializationContext. - Renamed DeserializeTypeMetadata to JsonDeserializeTypeMetadata; TypeMetadata to JsonTypeMetadata, each in their own files. - Updated all method signatures and internal references to use new names. - Simplified BinaryDeserializeTypeMetadata by removing internal property dictionary. No changes to public APIs; improves code clarity and maintainability.
This commit is contained in:
parent
f875738b08
commit
60ca154c6f
|
|
@ -10,8 +10,6 @@ public static partial class AcBinaryDeserializer
|
||||||
{
|
{
|
||||||
internal sealed class BinaryDeserializeTypeMetadata : BinaryTypeMetadataBase
|
internal sealed class BinaryDeserializeTypeMetadata : BinaryTypeMetadataBase
|
||||||
{
|
{
|
||||||
private readonly FrozenDictionary<string, BinaryPropertySetterInfo> _properties;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Properties array ordered alphabetically by name for index-based lookup.
|
/// Properties array ordered alphabetically by name for index-based lookup.
|
||||||
/// This matches the serializer's ordering, enabling O(1) array access.
|
/// This matches the serializer's ordering, enabling O(1) array access.
|
||||||
|
|
@ -27,10 +25,6 @@ public static partial class AcBinaryDeserializer
|
||||||
{
|
{
|
||||||
PropertiesArray[i] = new BinaryPropertySetterInfo(orderedProperties[i], type);
|
PropertiesArray[i] = new BinaryPropertySetterInfo(orderedProperties[i], type);
|
||||||
}
|
}
|
||||||
|
|
||||||
_properties = PropertiesArray.Length == 0
|
|
||||||
? FrozenDictionary<string, BinaryPropertySetterInfo>.Empty
|
|
||||||
: PropertiesArray.ToFrozenDictionary(static p => p.Name, static p => p, StringComparer.Ordinal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -39,10 +33,6 @@ public static partial class AcBinaryDeserializer
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public BinaryPropertySetterInfo? GetPropertyByIndex(int index)
|
public BinaryPropertySetterInfo? GetPropertyByIndex(int index)
|
||||||
=> (uint)index < (uint)PropertiesArray.Length ? PropertiesArray[index] : null;
|
=> (uint)index < (uint)PropertiesArray.Length ? PropertiesArray[index] : null;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public bool TryGetProperty(string name, out BinaryPropertySetterInfo? propertyInfo)
|
|
||||||
=> _properties.TryGetValue(name, out propertyInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ public static partial class AcBinaryDeserializer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static int[] GetIndexMapping(Type sourceType, Type destType, PropertyMapperDelegate? customMapper)
|
private static int[] GetIndexMapping(Type sourceType, Type destType, PropertyMapperDelegate? customMapper)
|
||||||
=> IndexMappingCache.GetOrBuild(sourceType, destType, customMapper, CrossTypeDeserializerBase.GetOrderedProperties);
|
=> IndexMappingCache.GetOrBuild(sourceType, destType, customMapper, DeserializeCrossTypeBase.GetOrderedProperties);
|
||||||
|
|
||||||
#region Cross-Type Deserialization
|
#region Cross-Type Deserialization
|
||||||
|
|
||||||
|
|
@ -42,14 +42,14 @@ public static partial class AcBinaryDeserializer
|
||||||
public static TDest? Deserialize<TSource, TDest>(ReadOnlySpan<byte> data, AcBinarySerializerOptions options)
|
public static TDest? Deserialize<TSource, TDest>(ReadOnlySpan<byte> data, AcBinarySerializerOptions options)
|
||||||
{
|
{
|
||||||
// Early exit checks
|
// Early exit checks
|
||||||
if (CrossTypeDeserializerBase.IsEmptyData(data, BinaryTypeCode.Null))
|
if (DeserializeCrossTypeBase.IsEmptyData(data, BinaryTypeCode.Null))
|
||||||
return default;
|
return default;
|
||||||
|
|
||||||
var sourceType = typeof(TSource);
|
var sourceType = typeof(TSource);
|
||||||
var destType = typeof(TDest);
|
var destType = typeof(TDest);
|
||||||
|
|
||||||
// Fast path: same type
|
// Fast path: same type
|
||||||
if (CrossTypeDeserializerBase.IsSameType(sourceType, destType))
|
if (DeserializeCrossTypeBase.IsSameType(sourceType, destType))
|
||||||
return Deserialize<TDest>(data, options);
|
return Deserialize<TDest>(data, options);
|
||||||
|
|
||||||
// Cross-type path: use index mapping
|
// Cross-type path: use index mapping
|
||||||
|
|
@ -117,17 +117,17 @@ public static partial class AcBinaryDeserializer
|
||||||
where TDest : class
|
where TDest : class
|
||||||
{
|
{
|
||||||
// Validation
|
// Validation
|
||||||
CrossTypeDeserializerBase.ValidatePopulateTarget(target);
|
DeserializeCrossTypeBase.ValidatePopulateTarget(target);
|
||||||
|
|
||||||
// Early exit checks
|
// Early exit checks
|
||||||
if (CrossTypeDeserializerBase.IsEmptyData(data, BinaryTypeCode.Null))
|
if (DeserializeCrossTypeBase.IsEmptyData(data, BinaryTypeCode.Null))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var sourceType = typeof(TSource);
|
var sourceType = typeof(TSource);
|
||||||
var destType = typeof(TDest);
|
var destType = typeof(TDest);
|
||||||
|
|
||||||
// Fast path: same type
|
// Fast path: same type
|
||||||
if (CrossTypeDeserializerBase.IsSameType(sourceType, destType))
|
if (DeserializeCrossTypeBase.IsSameType(sourceType, destType))
|
||||||
{
|
{
|
||||||
Populate(data, target, options);
|
Populate(data, target, options);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace AyCode.Core.Serializers;
|
||||||
/// Utility class providing common cross-type deserialization functionality.
|
/// Utility class providing common cross-type deserialization functionality.
|
||||||
/// Shared by both JSON and Binary deserializers.
|
/// Shared by both JSON and Binary deserializers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CrossTypeDeserializerBase
|
public static class DeserializeCrossTypeBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets ordered properties for a type using stable PropertyIndex ordering.
|
/// Gets ordered properties for a type using stable PropertyIndex ordering.
|
||||||
|
|
@ -5,7 +5,7 @@ namespace AyCode.Core.Serializers.Jsons;
|
||||||
|
|
||||||
public static partial class AcJsonDeserializer
|
public static partial class AcJsonDeserializer
|
||||||
{
|
{
|
||||||
private static class DeserializationContextPool
|
private static class JsonDeserializationContextPool
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentQueue<DeserializationContext> Pool = new();
|
private static readonly ConcurrentQueue<DeserializationContext> Pool = new();
|
||||||
private const int MaxPoolSize = 16;
|
private const int MaxPoolSize = 16;
|
||||||
|
|
@ -9,22 +9,22 @@ namespace AyCode.Core.Serializers.Jsons;
|
||||||
|
|
||||||
public static partial class AcJsonDeserializer
|
public static partial class AcJsonDeserializer
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<Type, DeserializeTypeMetadata> TypeMetadataCache = new();
|
private static readonly ConcurrentDictionary<Type, JsonDeserializeTypeMetadata> TypeMetadataCache = new();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static DeserializeTypeMetadata GetTypeMetadata(in Type type)
|
private static JsonDeserializeTypeMetadata GetTypeMetadata(in Type type)
|
||||||
=> TypeMetadataCache.GetOrAdd(type, static t => new DeserializeTypeMetadata(t));
|
=> TypeMetadataCache.GetOrAdd(type, static t => new JsonDeserializeTypeMetadata(t));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// JSON deserialization type metadata.
|
/// JSON deserialization type metadata.
|
||||||
/// Extends DeserializeTypeMetadataBase which provides cached IId info.
|
/// Extends DeserializeTypeMetadataBase which provides cached IId info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private sealed class DeserializeTypeMetadata : DeserializeTypeMetadataBase
|
private sealed class JsonDeserializeTypeMetadata : DeserializeTypeMetadataBase
|
||||||
{
|
{
|
||||||
public FrozenDictionary<string, PropertySetterInfo> PropertySettersFrozen { get; }
|
public FrozenDictionary<string, PropertySetterInfo> PropertySettersFrozen { get; }
|
||||||
public PropertySetterInfo[] PropertiesArray { get; } // Array for fast UTF8 linear scan (small objects)
|
public PropertySetterInfo[] PropertiesArray { get; } // Array for fast UTF8 linear scan (small objects)
|
||||||
|
|
||||||
public DeserializeTypeMetadata(Type type) : base(type)
|
public JsonDeserializeTypeMetadata(Type type) : base(type)
|
||||||
{
|
{
|
||||||
var props = GetSerializableProperties(type, requiresRead: true, requiresWrite: true).ToList();
|
var props = GetSerializableProperties(type, requiresRead: true, requiresWrite: true).ToList();
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ public static partial class AcJsonDeserializer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copies properties from source to target using JSON metadata.
|
/// Copies properties from source to target using JSON metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void CopyPropertiesJson(object source, object target, DeserializeTypeMetadata metadata)
|
private static void CopyPropertiesJson(object source, object target, JsonDeserializeTypeMetadata metadata)
|
||||||
{
|
{
|
||||||
foreach (var prop in metadata.PropertiesArray)
|
foreach (var prop in metadata.PropertiesArray)
|
||||||
{
|
{
|
||||||
|
|
@ -120,7 +120,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PopulateObjectInternal(in JsonElement element, object target, DeserializeTypeMetadata metadata, DeserializationContext context, int depth)
|
private static void PopulateObjectInternal(in JsonElement element, object target, JsonDeserializeTypeMetadata metadata, DeserializationContext context, int depth)
|
||||||
{
|
{
|
||||||
var propsDict = metadata.PropertySettersFrozen;
|
var propsDict = metadata.PropertySettersFrozen;
|
||||||
var nextDepth = depth + 1;
|
var nextDepth = depth + 1;
|
||||||
|
|
@ -143,7 +143,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PopulateObjectInternalMerge(in JsonElement element, object target, DeserializeTypeMetadata metadata, DeserializationContext context, int depth)
|
private static void PopulateObjectInternalMerge(in JsonElement element, object target, JsonDeserializeTypeMetadata metadata, DeserializationContext context, int depth)
|
||||||
{
|
{
|
||||||
var propsDict = metadata.PropertySettersFrozen;
|
var propsDict = metadata.PropertySettersFrozen;
|
||||||
var nextDepth = depth + 1;
|
var nextDepth = depth + 1;
|
||||||
|
|
@ -234,7 +234,7 @@ public static partial class AcJsonDeserializer
|
||||||
var nextDepth = depth + 1;
|
var nextDepth = depth + 1;
|
||||||
|
|
||||||
// ChainMode: Use cached IId info from element type metadata (no runtime reflection!)
|
// ChainMode: Use cached IId info from element type metadata (no runtime reflection!)
|
||||||
DeserializeTypeMetadata? elementMetadata = null;
|
JsonDeserializeTypeMetadata? elementMetadata = null;
|
||||||
if (context.IsChainMode && !IsPrimitiveOrStringFast(elementType))
|
if (context.IsChainMode && !IsPrimitiveOrStringFast(elementType))
|
||||||
{
|
{
|
||||||
elementMetadata = GetTypeMetadata(elementType);
|
elementMetadata = GetTypeMetadata(elementType);
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ public static partial class AcJsonDeserializer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read object from reader when we're already at StartObject.
|
/// Read object from reader when we're already at StartObject.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static object? ReadObjectFromReaderAtStart(ref Utf8JsonReader reader, Type targetType, DeserializeTypeMetadata metadata, byte maxDepth, int depth)
|
private static object? ReadObjectFromReaderAtStart(ref Utf8JsonReader reader, Type targetType, JsonDeserializeTypeMetadata metadata, byte maxDepth, int depth)
|
||||||
{
|
{
|
||||||
if (depth > maxDepth)
|
if (depth > maxDepth)
|
||||||
{
|
{
|
||||||
|
|
@ -380,7 +380,7 @@ public static partial class AcJsonDeserializer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populate object using Utf8JsonReader streaming (no DOM allocation).
|
/// Populate object using Utf8JsonReader streaming (no DOM allocation).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void PopulateObjectWithUtf8Reader(string json, object target, DeserializeTypeMetadata metadata, byte maxDepth)
|
private static void PopulateObjectWithUtf8Reader(string json, object target, JsonDeserializeTypeMetadata metadata, byte maxDepth)
|
||||||
{
|
{
|
||||||
var (buffer, length) = GetUtf8Bytes(json);
|
var (buffer, length) = GetUtf8Bytes(json);
|
||||||
try
|
try
|
||||||
|
|
@ -442,7 +442,7 @@ public static partial class AcJsonDeserializer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Populate object with merge semantics from Utf8JsonReader.
|
/// Populate object with merge semantics from Utf8JsonReader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void PopulateObjectMergeFromReader(ref Utf8JsonReader reader, object target, DeserializeTypeMetadata metadata, byte maxDepth, int depth)
|
private static void PopulateObjectMergeFromReader(ref Utf8JsonReader reader, object target, JsonDeserializeTypeMetadata metadata, byte maxDepth, int depth)
|
||||||
{
|
{
|
||||||
var nextDepth = depth + 1;
|
var nextDepth = depth + 1;
|
||||||
var maxDepthReached = nextDepth > maxDepth;
|
var maxDepthReached = nextDepth > maxDepth;
|
||||||
|
|
@ -607,7 +607,7 @@ public static partial class AcJsonDeserializer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy properties from source to target using metadata.
|
/// Copy properties from source to target using metadata.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void CopyProperties(object source, object target, DeserializeTypeMetadata metadata)
|
private static void CopyProperties(object source, object target, JsonDeserializeTypeMetadata metadata)
|
||||||
{
|
{
|
||||||
foreach (var prop in metadata.PropertySettersFrozen.Values)
|
foreach (var prop in metadata.PropertySettersFrozen.Values)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ public static partial class AcJsonDeserializer
|
||||||
|
|
||||||
var jsonBytes = utf8Json.ToArray();
|
var jsonBytes = utf8Json.ToArray();
|
||||||
using var doc = JsonDocument.Parse(jsonBytes);
|
using var doc = JsonDocument.Parse(jsonBytes);
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
||||||
|
|
@ -85,7 +85,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AcJsonDeserializationException) { throw; }
|
catch (AcJsonDeserializationException) { throw; }
|
||||||
|
|
@ -135,7 +135,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
|
|
||||||
using var doc = JsonDocument.Parse(json);
|
using var doc = JsonDocument.Parse(json);
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
||||||
|
|
@ -144,7 +144,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AcJsonDeserializationException) { throw; }
|
catch (AcJsonDeserializationException) { throw; }
|
||||||
|
|
@ -202,7 +202,7 @@ public static partial class AcJsonDeserializer
|
||||||
// Reference handling requires DOM - copy to array for JsonDocument.Parse
|
// Reference handling requires DOM - copy to array for JsonDocument.Parse
|
||||||
var jsonBytes = Encoding.UTF8.GetBytes(json);
|
var jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||||
using var doc = JsonDocument.Parse(jsonBytes);
|
using var doc = JsonDocument.Parse(jsonBytes);
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
||||||
|
|
@ -211,7 +211,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AcJsonDeserializationException) { throw; }
|
catch (AcJsonDeserializationException) { throw; }
|
||||||
|
|
@ -287,7 +287,7 @@ public static partial class AcJsonDeserializer
|
||||||
// Reference handling requires DOM - copy to array for JsonDocument.Parse
|
// Reference handling requires DOM - copy to array for JsonDocument.Parse
|
||||||
var jsonBytes = utf8Json.ToArray();
|
var jsonBytes = utf8Json.ToArray();
|
||||||
using var doc = JsonDocument.Parse(jsonBytes);
|
using var doc = JsonDocument.Parse(jsonBytes);
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
var result = ReadValue(doc.RootElement, targetType, context, 0);
|
||||||
|
|
@ -296,7 +296,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AcJsonDeserializationException) { throw; }
|
catch (AcJsonDeserializationException) { throw; }
|
||||||
|
|
@ -398,7 +398,7 @@ public static partial class AcJsonDeserializer
|
||||||
using var doc = JsonDocument.Parse(json);
|
using var doc = JsonDocument.Parse(json);
|
||||||
var rootElement = doc.RootElement;
|
var rootElement = doc.RootElement;
|
||||||
|
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
context.IsMergeMode = true;
|
context.IsMergeMode = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -426,7 +426,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (AcJsonDeserializationException) { throw; }
|
catch (AcJsonDeserializationException) { throw; }
|
||||||
|
|
@ -505,7 +505,7 @@ public static partial class AcJsonDeserializer
|
||||||
|
|
||||||
var doc = JsonDocument.Parse(json);
|
var doc = JsonDocument.Parse(json);
|
||||||
var chainTracker = new AcSerializerCommon.ChainReferenceTracker();
|
var chainTracker = new AcSerializerCommon.ChainReferenceTracker();
|
||||||
var context = DeserializationContextPool.Get(options);
|
var context = JsonDeserializationContextPool.Get(options);
|
||||||
context.ChainTracker = chainTracker;
|
context.ChainTracker = chainTracker;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -516,7 +516,7 @@ public static partial class AcJsonDeserializer
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(context);
|
JsonDeserializationContextPool.Return(context);
|
||||||
doc.Dispose();
|
doc.Dispose();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
@ -629,7 +629,7 @@ public static partial class AcJsonDeserializer
|
||||||
|
|
||||||
if (_context != null)
|
if (_context != null)
|
||||||
{
|
{
|
||||||
DeserializationContextPool.Return(_context);
|
JsonDeserializationContextPool.Return(_context);
|
||||||
_context = null;
|
_context = null;
|
||||||
}
|
}
|
||||||
_document?.Dispose();
|
_document?.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,22 @@ public static partial class AcJsonSerializer
|
||||||
{
|
{
|
||||||
private static class SerializationContextPool
|
private static class SerializationContextPool
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentQueue<SerializationContext> Pool = new();
|
private static readonly ConcurrentQueue<JsonSerializationContext> Pool = new();
|
||||||
private const int MaxPoolSize = 16;
|
private const int MaxPoolSize = 16;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static SerializationContext Get(in AcJsonSerializerOptions options)
|
public static JsonSerializationContext Get(in AcJsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (Pool.TryDequeue(out var context))
|
if (Pool.TryDequeue(out var context))
|
||||||
{
|
{
|
||||||
context.Reset(options);
|
context.Reset(options);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
return new SerializationContext(options);
|
return new JsonSerializationContext(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Return(SerializationContext context)
|
public static void Return(JsonSerializationContext context)
|
||||||
{
|
{
|
||||||
if (Pool.Count < MaxPoolSize)
|
if (Pool.Count < MaxPoolSize)
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ public static partial class AcJsonSerializer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class SerializationContext : IDisposable
|
private sealed class JsonSerializationContext : IDisposable
|
||||||
{
|
{
|
||||||
private readonly ArrayBufferWriter<byte> _buffer;
|
private readonly ArrayBufferWriter<byte> _buffer;
|
||||||
public Utf8JsonWriter Writer { get; private set; }
|
public Utf8JsonWriter Writer { get; private set; }
|
||||||
|
|
@ -52,7 +52,7 @@ public static partial class AcJsonSerializer
|
||||||
SkipValidation = true // Skip validation for performance
|
SkipValidation = true // Skip validation for performance
|
||||||
};
|
};
|
||||||
|
|
||||||
public SerializationContext(in AcJsonSerializerOptions options)
|
public JsonSerializationContext(in AcJsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
_buffer = new ArrayBufferWriter<byte>(4096);
|
_buffer = new ArrayBufferWriter<byte>(4096);
|
||||||
Writer = new Utf8JsonWriter(_buffer, WriterOptions);
|
Writer = new Utf8JsonWriter(_buffer, WriterOptions);
|
||||||
|
|
@ -7,17 +7,17 @@ namespace AyCode.Core.Serializers.Jsons;
|
||||||
|
|
||||||
public static partial class AcJsonSerializer
|
public static partial class AcJsonSerializer
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<Type, TypeMetadata> TypeMetadataCache = new();
|
private static readonly ConcurrentDictionary<Type, JsonTypeMetadata> TypeMetadataCache = new();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static TypeMetadata GetTypeMetadata(in Type type)
|
private static JsonTypeMetadata GetTypeMetadata(in Type type)
|
||||||
=> TypeMetadataCache.GetOrAdd(type, static t => new TypeMetadata(t));
|
=> TypeMetadataCache.GetOrAdd(type, static t => new JsonTypeMetadata(t));
|
||||||
|
|
||||||
private sealed class TypeMetadata : TypeMetadataBase
|
private sealed class JsonTypeMetadata : TypeMetadataBase
|
||||||
{
|
{
|
||||||
public PropertyAccessor[] Properties { get; }
|
public PropertyAccessor[] Properties { get; }
|
||||||
|
|
||||||
public TypeMetadata(Type type) : base(type)
|
public JsonTypeMetadata(Type type) : base(type)
|
||||||
{
|
{
|
||||||
Properties = GetSerializableProperties(type, requiresRead: true, requiresWrite: false)
|
Properties = GetSerializableProperties(type, requiresRead: true, requiresWrite: false)
|
||||||
.Select(p => new PropertyAccessor(p, type))
|
.Select(p => new PropertyAccessor(p, type))
|
||||||
|
|
@ -121,7 +121,7 @@ public static partial class AcJsonSerializer
|
||||||
|
|
||||||
#region Reference Scanning
|
#region Reference Scanning
|
||||||
|
|
||||||
private static void ScanReferences(object? value, SerializationContext context, int depth)
|
private static void ScanReferences(object? value, JsonSerializationContext context, int depth)
|
||||||
{
|
{
|
||||||
if (value == null || depth > context.MaxDepth) return;
|
if (value == null || depth > context.MaxDepth) return;
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ public static partial class AcJsonSerializer
|
||||||
|
|
||||||
#region Serialization
|
#region Serialization
|
||||||
|
|
||||||
private static void WriteValue(object? value, SerializationContext context, int depth)
|
private static void WriteValue(object? value, JsonSerializationContext context, int depth)
|
||||||
{
|
{
|
||||||
if (value == null) { context.Writer.WriteNullValue(); return; }
|
if (value == null) { context.Writer.WriteNullValue(); return; }
|
||||||
|
|
||||||
|
|
@ -167,7 +167,7 @@ public static partial class AcJsonSerializer
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void WriteObject(object value, in Type type, SerializationContext context, int depth)
|
private static void WriteObject(object value, in Type type, JsonSerializationContext context, int depth)
|
||||||
{
|
{
|
||||||
var writer = context.Writer;
|
var writer = context.Writer;
|
||||||
|
|
||||||
|
|
@ -207,7 +207,7 @@ public static partial class AcJsonSerializer
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void WriteArray(IEnumerable enumerable, SerializationContext context, int depth)
|
private static void WriteArray(IEnumerable enumerable, JsonSerializationContext context, int depth)
|
||||||
{
|
{
|
||||||
var writer = context.Writer;
|
var writer = context.Writer;
|
||||||
writer.WriteStartArray();
|
writer.WriteStartArray();
|
||||||
|
|
@ -222,7 +222,7 @@ public static partial class AcJsonSerializer
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void WriteDictionary(IDictionary dictionary, SerializationContext context, int depth)
|
private static void WriteDictionary(IDictionary dictionary, JsonSerializationContext context, int depth)
|
||||||
{
|
{
|
||||||
var writer = context.Writer;
|
var writer = context.Writer;
|
||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue