using System; using System.Collections.Generic; using System.Linq; using FullSerializer.Internal; namespace FullSerializer { /// /// The serialization converter allows for customization of the serialization process. /// /// You do not want to derive from this class - there is no way to actually use it within /// the serializer.. Instead, derive from either fsConverter or fsDirectConverter public abstract class fsBaseConverter { /// /// The serializer that was owns this converter. /// public fsSerializer Serializer; /// /// Construct an object instance that will be passed to TryDeserialize. This should **not** /// deserialize the object. /// /// The data the object was serialized with. /// The field/property type that is storing the instance. /// An object instance public virtual object CreateInstance(fsData data, Type storageType) { if (RequestCycleSupport(storageType)) { throw new InvalidOperationException("Please override CreateInstance for " + GetType().FullName + "; the object graph for " + storageType + " can contain potentially contain cycles, so separated instance creation " + "is needed"); } return storageType; } /// /// If true, then the serializer will support cyclic references with the given converted /// type. /// /// The field/property type that is currently storing the object /// that is being serialized. public virtual bool RequestCycleSupport(Type storageType) { if (storageType == typeof(string)) return false; return storageType.Resolve().IsClass || storageType.Resolve().IsInterface; } /// /// If true, then the serializer will include inheritance data for the given converter. /// /// The field/property type that is currently storing the object /// that is being serialized. public virtual bool RequestInheritanceSupport(Type storageType) { return storageType.Resolve().IsSealed == false; } /// /// Serialize the actual object into the given data storage. /// /// The object instance to serialize. This will never be null. /// The serialized state. /// The field/property type that is storing this instance. /// If serialization was successful. public abstract fsResult TrySerialize(object instance, out fsData serialized, Type storageType); /// /// Deserialize data into the object instance. /// /// Serialization data to deserialize from. /// The object instance to deserialize into. /// The field/property type that is storing the instance. /// True if serialization was successful, false otherwise. public abstract fsResult TryDeserialize(fsData data, ref object instance, Type storageType); protected fsResult FailExpectedType(fsData data, params fsDataType[] types) { return fsResult.Fail(GetType().Name + " expected one of " + string.Join(", ", types.Select(t => t.ToString()).ToArray()) + " but got " + data.Type + " in " + data); } protected fsResult CheckType(fsData data, fsDataType type) { if (data.Type != type) { return fsResult.Fail(GetType().Name + " expected " + type + " but got " + data.Type + " in " + data); } return fsResult.Success; } protected fsResult CheckKey(fsData data, string key, out fsData subitem) { return CheckKey(data.AsDictionary, key, out subitem); } protected fsResult CheckKey(Dictionary data, string key, out fsData subitem) { if (data.TryGetValue(key, out subitem) == false) { return fsResult.Fail(GetType().Name + " requires a <" + key + "> key in the data " + data); } return fsResult.Success; } protected fsResult SerializeMember(Dictionary data, Type overrideConverterType, string name, T value) { fsData memberData; var result = Serializer.TrySerialize(typeof(T), overrideConverterType, value, out memberData); if (result.Succeeded) data[name] = memberData; return result; } protected fsResult DeserializeMember(Dictionary data, Type overrideConverterType, string name, out T value) { fsData memberData; if (data.TryGetValue(name, out memberData) == false) { value = default(T); return fsResult.Fail("Unable to find member \"" + name + "\""); } object storage = null; var result = Serializer.TryDeserialize(memberData, typeof(T), overrideConverterType, ref storage); value = (T)storage; return result; } } }