| File: System\Runtime\Serialization\Json\JsonCollectionDataContract.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.DataContractSerialization\src\System.Private.DataContractSerialization.csproj (System.Private.DataContractSerialization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.DataContracts; using System.Threading; using System.Xml; namespace System.Runtime.Serialization.Json { internal sealed class JsonCollectionDataContract : JsonDataContract { private readonly JsonCollectionDataContractCriticalHelper _helper; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public JsonCollectionDataContract(CollectionDataContract traditionalDataContract) : base(new JsonCollectionDataContractCriticalHelper(traditionalDataContract)) { _helper = (base.Helper as JsonCollectionDataContractCriticalHelper)!; } internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] get { if (_helper.JsonFormatReaderDelegate == null) { lock (this) { if (_helper.JsonFormatReaderDelegate == null) { JsonFormatCollectionReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadCollection; } else { tempDelegate = new JsonFormatReaderGenerator().GenerateCollectionReader(TraditionalCollectionDataContract); } Interlocked.MemoryBarrier(); _helper.JsonFormatReaderDelegate = tempDelegate; } } } return _helper.JsonFormatReaderDelegate; } } internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] get { if (_helper.JsonFormatGetOnlyReaderDelegate == null) { lock (this) { if (_helper.JsonFormatGetOnlyReaderDelegate == null) { CollectionKind kind = this.TraditionalCollectionDataContract.Kind; if (this.TraditionalDataContract.UnderlyingType.IsInterface && (kind == CollectionKind.Enumerable || kind == CollectionKind.Collection || kind == CollectionKind.GenericEnumerable)) { throw new InvalidDataContractException(SR.Format(SR.GetOnlyCollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(this.TraditionalDataContract.UnderlyingType))); } JsonFormatGetOnlyCollectionReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadGetOnlyCollection; } else { tempDelegate = new JsonFormatReaderGenerator().GenerateGetOnlyCollectionReader(TraditionalCollectionDataContract); } Interlocked.MemoryBarrier(); _helper.JsonFormatGetOnlyReaderDelegate = tempDelegate; } } } return _helper.JsonFormatGetOnlyReaderDelegate; } } internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate { [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] get { if (_helper.JsonFormatWriterDelegate == null) { lock (this) { if (_helper.JsonFormatWriterDelegate == null) { JsonFormatCollectionWriterDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { tempDelegate = ReflectionJsonFormatWriter.ReflectionWriteCollection; } else { tempDelegate = new JsonFormatWriterGenerator().GenerateCollectionWriter(TraditionalCollectionDataContract); } Interlocked.MemoryBarrier(); _helper.JsonFormatWriterDelegate = tempDelegate; } } } return _helper.JsonFormatWriterDelegate; } } private CollectionDataContract TraditionalCollectionDataContract => _helper.TraditionalCollectionDataContract; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public override object? ReadJsonValueCore(XmlReaderDelegator jsonReader, XmlObjectSerializerReadContextComplexJson? context) { Debug.Assert(context != null); jsonReader.Read(); object? o = null; if (context.IsGetOnlyCollection) { // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset. context.IsGetOnlyCollection = false; JsonFormatGetOnlyReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract); } else { o = JsonFormatReaderDelegate(jsonReader, context, XmlDictionaryString.Empty, JsonGlobals.itemDictionaryString, TraditionalCollectionDataContract); } jsonReader.ReadEndElement(); return o; } [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public override void WriteJsonValueCore(XmlWriterDelegator jsonWriter, object obj, XmlObjectSerializerWriteContextComplexJson? context, RuntimeTypeHandle declaredTypeHandle) { Debug.Assert(context != null); // IsGetOnlyCollection value has already been used to create current collectiondatacontract, value can now be reset. context.IsGetOnlyCollection = false; JsonFormatWriterDelegate(jsonWriter, obj, context, TraditionalCollectionDataContract); } private sealed class JsonCollectionDataContractCriticalHelper : JsonDataContractCriticalHelper { private JsonFormatCollectionReaderDelegate? _jsonFormatReaderDelegate; private JsonFormatGetOnlyCollectionReaderDelegate? _jsonFormatGetOnlyReaderDelegate; private JsonFormatCollectionWriterDelegate? _jsonFormatWriterDelegate; private readonly CollectionDataContract _traditionalCollectionDataContract; [RequiresDynamicCode(DataContract.SerializerAOTWarning)] [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public JsonCollectionDataContractCriticalHelper(CollectionDataContract traditionalDataContract) : base(traditionalDataContract) { _traditionalCollectionDataContract = traditionalDataContract; } internal JsonFormatCollectionReaderDelegate? JsonFormatReaderDelegate { get { return _jsonFormatReaderDelegate; } set { _jsonFormatReaderDelegate = value; } } internal JsonFormatGetOnlyCollectionReaderDelegate? JsonFormatGetOnlyReaderDelegate { get { return _jsonFormatGetOnlyReaderDelegate; } set { _jsonFormatGetOnlyReaderDelegate = value; } } internal JsonFormatCollectionWriterDelegate? JsonFormatWriterDelegate { get { return _jsonFormatWriterDelegate; } set { _jsonFormatWriterDelegate = value; } } internal CollectionDataContract TraditionalCollectionDataContract { get { return _traditionalCollectionDataContract; } } } } }