#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. #endregion using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.Serialization; using LC.Newtonsoft.Json.Linq; using LC.Newtonsoft.Json.Utilities; namespace LC.Newtonsoft.Json.Serialization { internal enum JsonContractType { None = 0, Object = 1, Array = 2, Primitive = 3, String = 4, Dictionary = 5, Dynamic = 6, Serializable = 7, Linq = 8 } /// /// Handles serialization callback events. /// /// The object that raised the callback event. /// The streaming context. public delegate void SerializationCallback(object o, StreamingContext context); /// /// Handles serialization error callback events. /// /// The object that raised the callback event. /// The streaming context. /// The error context. public delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext); /// /// Sets extension data for an object during deserialization. /// /// The object to set extension data on. /// The extension data key. /// The extension data value. public delegate void ExtensionDataSetter(object o, string key, object value); /// /// Gets extension data for an object during serialization. /// /// The object to set extension data on. public delegate IEnumerable> ExtensionDataGetter(object o); /// /// Contract details for a used by the . /// public abstract class JsonContract { internal bool IsNullable; internal bool IsConvertable; internal bool IsEnum; internal Type NonNullableUnderlyingType; internal ReadType InternalReadType; internal JsonContractType ContractType; internal bool IsReadOnlyOrFixedSize; internal bool IsSealed; internal bool IsInstantiable; private List _onDeserializedCallbacks; private IList _onDeserializingCallbacks; private IList _onSerializedCallbacks; private IList _onSerializingCallbacks; private IList _onErrorCallbacks; private Type _createdType; /// /// Gets the underlying type for the contract. /// /// The underlying type for the contract. public Type UnderlyingType { get; } /// /// Gets or sets the type created during deserialization. /// /// The type created during deserialization. public Type CreatedType { get => _createdType; set { _createdType = value; IsSealed = _createdType.IsSealed(); IsInstantiable = !(_createdType.IsInterface() || _createdType.IsAbstract()); } } /// /// Gets or sets whether this type contract is serialized as a reference. /// /// Whether this type contract is serialized as a reference. public bool? IsReference { get; set; } /// /// Gets or sets the default for this contract. /// /// The converter. public JsonConverter Converter { get; set; } /// /// Gets the internally resolved for the contract's type. /// This converter is used as a fallback converter when no other converter is resolved. /// Setting will always override this converter. /// public JsonConverter InternalConverter { get; internal set; } /// /// Gets or sets all methods called immediately after deserialization of the object. /// /// The methods called immediately after deserialization of the object. public IList OnDeserializedCallbacks { get { if (_onDeserializedCallbacks == null) { _onDeserializedCallbacks = new List(); } return _onDeserializedCallbacks; } } /// /// Gets or sets all methods called during deserialization of the object. /// /// The methods called during deserialization of the object. public IList OnDeserializingCallbacks { get { if (_onDeserializingCallbacks == null) { _onDeserializingCallbacks = new List(); } return _onDeserializingCallbacks; } } /// /// Gets or sets all methods called after serialization of the object graph. /// /// The methods called after serialization of the object graph. public IList OnSerializedCallbacks { get { if (_onSerializedCallbacks == null) { _onSerializedCallbacks = new List(); } return _onSerializedCallbacks; } } /// /// Gets or sets all methods called before serialization of the object. /// /// The methods called before serialization of the object. public IList OnSerializingCallbacks { get { if (_onSerializingCallbacks == null) { _onSerializingCallbacks = new List(); } return _onSerializingCallbacks; } } /// /// Gets or sets all method called when an error is thrown during the serialization of the object. /// /// The methods called when an error is thrown during the serialization of the object. public IList OnErrorCallbacks { get { if (_onErrorCallbacks == null) { _onErrorCallbacks = new List(); } return _onErrorCallbacks; } } /// /// Gets or sets the default creator method used to create the object. /// /// The default creator method used to create the object. public Func DefaultCreator { get; set; } /// /// Gets or sets a value indicating whether the default creator is non-public. /// /// true if the default object creator is non-public; otherwise, false. public bool DefaultCreatorNonPublic { get; set; } internal JsonContract(Type underlyingType) { ValidationUtils.ArgumentNotNull(underlyingType, nameof(underlyingType)); UnderlyingType = underlyingType; // resolve ByRef types // typically comes from in and ref parameters on methods/ctors underlyingType = ReflectionUtils.EnsureNotByRefType(underlyingType); IsNullable = ReflectionUtils.IsNullable(underlyingType); NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType; CreatedType = NonNullableUnderlyingType; IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType); IsEnum = NonNullableUnderlyingType.IsEnum(); InternalReadType = ReadType.Read; } internal void InvokeOnSerializing(object o, StreamingContext context) { if (_onSerializingCallbacks != null) { foreach (SerializationCallback callback in _onSerializingCallbacks) { callback(o, context); } } } internal void InvokeOnSerialized(object o, StreamingContext context) { if (_onSerializedCallbacks != null) { foreach (SerializationCallback callback in _onSerializedCallbacks) { callback(o, context); } } } internal void InvokeOnDeserializing(object o, StreamingContext context) { if (_onDeserializingCallbacks != null) { foreach (SerializationCallback callback in _onDeserializingCallbacks) { callback(o, context); } } } internal void InvokeOnDeserialized(object o, StreamingContext context) { if (_onDeserializedCallbacks != null) { foreach (SerializationCallback callback in _onDeserializedCallbacks) { callback(o, context); } } } internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext) { if (_onErrorCallbacks != null) { foreach (SerializationErrorCallback callback in _onErrorCallbacks) { callback(o, context, errorContext); } } } internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo) { return (o, context) => callbackMethodInfo.Invoke(o, new object[] { context }); } internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo) { return (o, context, econtext) => callbackMethodInfo.Invoke(o, new object[] { context, econtext }); } } }