// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 using System.Runtime.Serialization; namespace QtVsTools.Json { /// /// Public interface of objects that allow deferred deserialization of their data. /// /// Base type of deferred data /// public interface IDeferrable { TBase Deserialize(IJsonData jsonData); } /// /// Provides deferred deserialization of a wrapped object, given the base class of a /// prototyped class hierarchy that will be searched for the actual deserialization class. /// /// Base of deferrable class hierarchy /// [DataContract] public class DeferredObject : Disposable, IDeferredObject where TBase : Prototyped, IDeferrable { private IJsonData jsonData; public TBase Object { get; private set; } object IDeferredObject.Object => Object; public bool HasData => Object != null; /// /// This constructor is used when serializing, to directly wrap an existing object. /// /// Object to wrap /// public DeferredObject(TBase obj) { Object = obj; } [OnDeserializing] // <-- Invoked by serializer before deserializing this object private void OnDeserializing(StreamingContext context) { // Store JSON data corresponding to this object jsonData = Serializer.GetCurrentJsonData(); } /// /// Performs a deferred deserialization to obtain a new wrapped object corresponding to the /// contents of the stored JSON data. The actual deserialization is delegated to the base /// prototype of the class hierarchy. This prototype is then responsible to find an /// appropriate class in the hierarchy and map the JSON data to an instance of the class. /// /// public void Deserialize() { Atomic(() => Object == null && jsonData != null, () => { Object = Prototyped.BasePrototype.Deserialize(jsonData); jsonData.Dispose(); jsonData = null; }); } protected override void DisposeManaged() { jsonData?.Dispose(); } public static implicit operator TBase(DeferredObject obj) { return obj.Object; } } }