//... fsResult Internal_Deserialize(fsData data, Type storageType, ref object result, Type overrideConverterType) { //$ref encountered. Do before inheritance. if (IsObjectReference(data)) { int refId = int.Parse(data.AsDictionary[KEY_OBJECT_REFERENCE].AsString); result = _references.GetReferenceObject(refId); return(fsResult.Success); } var deserializeResult = fsResult.Success; var objectType = result != null?result.GetType() : storageType; Type forwardMigrationPreviousType = null; // Gather processors and call OnBeforeDeserialize before anything var processors = GetProcessors(objectType); Invoke_OnBeforeDeserialize(processors, objectType, ref data); // If the serialized state contains type information, then we need to make sure to update our // objectType and data to the proper values so that when we construct an object instance later // and run deserialization we run it on the proper type. // $type if (IsTypeSpecified(data)) { var typeNameData = data.AsDictionary[KEY_INSTANCE_TYPE]; do { if (!typeNameData.IsString) { deserializeResult.AddMessage(string.Format("{0} value must be a string", KEY_INSTANCE_TYPE)); break; } var typeName = typeNameData.AsString; var type = ReflectionTools.GetType(typeName, storageType); if (type == null) { deserializeResult.AddMessage(string.Format("{0} type can not be resolved", typeName)); break; } var migrateAtt = type.RTGetAttribute <fsMigrateToAttribute>(true); if (migrateAtt != null) { // if migrating from another type, save the original type and mutate the current type if (!typeof(IMigratable).IsAssignableFrom(migrateAtt.targetType)) { throw new Exception("TargetType of [fsMigrateToAttribute] must implement IMigratable<T> with T being the target type"); } forwardMigrationPreviousType = type; if (type.IsGenericType && migrateAtt.targetType.IsGenericTypeDefinition) { type = migrateAtt.targetType.MakeGenericType(type.GetGenericArguments()); } else { type = migrateAtt.targetType; } } if (!storageType.IsAssignableFrom(type)) { deserializeResult.AddMessage(string.Format("Ignoring type specifier. Field or type {0} can't hold and instance of type {1}", storageType, type)); break; } objectType = type; } while (false); } var converter = GetConverter(objectType, overrideConverterType); if (converter == null) { return(fsResult.Warn(string.Format("No Converter available for {0}", objectType))); } // Construct an object instance if we don't have one already using actual objectType if (ReferenceEquals(result, null) || result.GetType() != objectType) { result = converter.CreateInstance(data, objectType); } // if migrating from another type, do migration now. if (forwardMigrationPreviousType != null) { //we deserialize versioning first on the old model type and then do migration var previousInstance = GetConverter(forwardMigrationPreviousType, null).CreateInstance(data, forwardMigrationPreviousType); TryDeserializeVersioning(ref previousInstance, ref data); TryDeserializeMigration(ref result, ref data, forwardMigrationPreviousType, previousInstance); } else { // if not a forward migration, try deserialize versioning as normal TryDeserializeVersioning(ref result, ref data); } // invoke callback with objectType Invoke_OnBeforeDeserializeAfterInstanceCreation(processors, objectType, result, ref data); // $id if (IsObjectDefinition(data)) { var sourceId = int.Parse(data.AsDictionary[KEY_OBJECT_DEFINITION].AsString); _references.AddReferenceWithId(sourceId, result); } // $content if (IsWrappedData(data)) { data = data.AsDictionary[KEY_CONTENT]; } // push collector TryPush(result); // must pass actual objectType deserializeResult += converter.TryDeserialize(data, ref result, objectType); if (deserializeResult.Succeeded) { Invoke_OnAfterDeserialize(processors, objectType, result); } // pop collector TryPop(result); return(deserializeResult); }
private fsResult TryParseObject(out fsData obj) { if (Character() != '{') { obj = null; return(MakeFailure("Expected initial { when parsing an object")); } // skip '{' if (TryMoveNext() == false) { obj = null; return(MakeFailure("Unexpected end of input when parsing an object")); } SkipSpace(); var result = new Dictionary <string, fsData>( fsGlobalConfig.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); while (HasValue() && Character() != '}') { fsResult failure; // parse the key SkipSpace(); string key; failure = TryParseString(out key); if (failure.Failed) { obj = null; return(failure); } SkipSpace(); // parse the ':' after the key if (HasValue() == false || Character() != ':' || TryMoveNext() == false) { obj = null; return(MakeFailure("Expected : after key \"" + key + "\"")); } SkipSpace(); // parse the value fsData value; failure = RunParse(out value); if (failure.Failed) { obj = null; return(failure); } result.Add(key, value); // parse the comma SkipSpace(); if (HasValue() && Character() == ',') { if (TryMoveNext() == false) { break; } SkipSpace(); } } // skip the final } if (HasValue() == false || Character() != '}' || TryMoveNext() == false) { obj = null; return(MakeFailure("No closing } for object")); } obj = new fsData(result); return(fsResult.Success); }
///---------------------------------------------------------------------------------------------- /// Serialize the given value. public fsResult TrySerialize(Type storageType, object instance, out fsData data) { return(TrySerialize(storageType, instance, out data, null)); }
///---------------------------------------------------------------------------------------------- /// Attempts to deserialize a value from a serialized state. public fsResult TryDeserialize(fsData data, Type storageType, ref object result) { return(TryDeserialize(data, storageType, ref result, null)); }
/// <summary> /// Serialize the given value. /// </summary> /// <param name="storageType">The type of field/property that stores the object instance. This is /// important particularly for inheritance, as a field storing an IInterface instance /// should have type information included.</param> /// <param name="overrideConverterType">An fsBaseConverter derived type that will be used to serialize /// the object instead of the converter found via the normal discovery mechanisms.</param> /// <param name="instance">The actual object instance to serialize.</param> /// <param name="data">The serialized state of the object.</param> /// <returns>If serialization was successful.</returns> public fsResult TrySerialize(Type storageType, Type overrideConverterType, object instance, out fsData data) { var processors = GetProcessors(instance == null ? storageType : instance.GetType()); // 主要是是条用processors的OnBeforeSerialize和ISerializationCallbackReceiver.OnBeforeSerialize方法 Invoke_OnBeforeSerialize(processors, storageType, instance); // 如果是null值的情况 // We always serialize null directly as null if (ReferenceEquals(instance, null)) { data = new fsData(); // // 调用fsObjectProcessor的OnAfterSerialize Invoke_OnAfterSerialize(processors, storageType, instance, ref data); return(fsResult.Success); } var result = InternalSerialize_1_ProcessCycles(storageType, overrideConverterType, instance, out data); Invoke_OnAfterSerialize(processors, storageType, instance, ref data); return(result); }
private static void Invoke_OnBeforeDeserializeAfterInstanceCreation(List <fsObjectProcessor> processors, Type storageType, object instance, ref fsData data) { for (int i = 0; i < processors.Count; ++i) { processors[i].OnBeforeDeserializeAfterInstanceCreation(storageType, instance, ref data); } }
/// <summary> /// Determines whether the specified object is equal to the current object. /// </summary> public bool Equals(fsData other) { if (other == null || Type != other.Type) { return(false); } switch (Type) { case fsDataType.Null: return(true); case fsDataType.Double: return(AsDouble == other.AsDouble || Math.Abs(AsDouble - other.AsDouble) < double.Epsilon); case fsDataType.Int64: return(AsInt64 == other.AsInt64); case fsDataType.Boolean: return(AsBool == other.AsBool); case fsDataType.String: return(AsString == other.AsString); case fsDataType.Array: var thisList = AsList; var otherList = other.AsList; if (thisList.Count != otherList.Count) { return(false); } for (int i = 0; i < thisList.Count; ++i) { if (thisList[i].Equals(otherList[i]) == false) { return(false); } } return(true); case fsDataType.Object: var thisDict = AsDictionary; var otherDict = other.AsDictionary; if (thisDict.Count != otherDict.Count) { return(false); } foreach (string key in thisDict.Keys) { if (otherDict.ContainsKey(key) == false) { return(false); } if (thisDict[key].Equals(otherDict[key]) == false) { return(false); } } return(true); } throw new Exception("Unknown data type"); }
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)); }
private fsResult InternalDeserialize_1_CycleReference(Type overrideConverterType, fsData data, Type storageType, ref object result, out List <fsObjectProcessor> processors) { // We handle object references first because we could be deserializing a cyclic type that is // inherited. If that is the case, then if we handle references after inheritances we will try // to create an object instance for an abstract/interface type. // While object construction should technically be two-pass, we can do it in // one pass because of how serialization happens. We traverse the serialization // graph in the same order during serialization and deserialization, so the first // time we encounter an object it'll always be the definition. Any times after that // it will be a reference. Because of this, if we encounter a reference then we // will have *always* already encountered the definition for it. // 判断data是否是Dict,并且是否有$ref字段 if (IsObjectReference(data)) { int refId = int.Parse(data.AsDictionary[Key_ObjectReference].AsString); result = _references.GetReferenceObject(refId); processors = GetProcessors(result.GetType()); return(fsResult.Success); } return(InternalDeserialize_3_Inheritance(overrideConverterType, data, storageType, ref result, out processors)); //return InternalDeserialize_2_Version(overrideConverterType, data, storageType, ref result, out processors); }
/* //PARADOXNOTION ADDITION * private fsResult InternalDeserialize_2_Version(Type overrideConverterType, fsData data, Type storageType, ref object result, out List<fsObjectProcessor> processors) { * if (IsVersioned(data)) { * // data is versioned, but we might not need to do a migration * string version = data.AsDictionary[Key_Version].AsString; * * fsOption<fsVersionedType> versionedType = fsVersionManager.GetVersionedType(storageType); * if (versionedType.HasValue && * versionedType.Value.VersionString != version) { * * // we have to do a migration * var deserializeResult = fsResult.Success; * * List<fsVersionedType> path; * deserializeResult += fsVersionManager.GetVersionImportPath(version, versionedType.Value, out path); * if (deserializeResult.Failed) { * processors = GetProcessors(storageType); * return deserializeResult; * } * * // deserialize as the original type * deserializeResult += InternalDeserialize_3_Inheritance(overrideConverterType, data, path[0].ModelType, ref result, out processors); * if (deserializeResult.Failed) return deserializeResult; * * // TODO: we probably should be invoking object processors all along this pipeline * for (int i = 1; i < path.Count; ++i) { * result = path[i].Migrate(result); * } * * // Our data contained an object definition ($id) that was added to _references in step 4. * // However, in case we are doing versioning, it will contain the old version. * // To make sure future references to this object end up referencing the migrated version, * // we must update the reference. * if (IsObjectDefinition(data)) { * int sourceId = int.Parse(data.AsDictionary[Key_ObjectDefinition].AsString); * _references.AddReferenceWithId(sourceId, result); * } * * processors = GetProcessors(deserializeResult.GetType()); * return deserializeResult; * } * } * * return InternalDeserialize_3_Inheritance(overrideConverterType, data, storageType, ref result, out processors); * } */ private fsResult InternalDeserialize_3_Inheritance(Type overrideConverterType, fsData data, Type storageType, ref object result, out List <fsObjectProcessor> processors) { var deserializeResult = fsResult.Success; // We wait until here to actually Invoke_OnBeforeDeserialize because we do not // have the correct set of processors to invoke until *after* we have resolved // the proper type to use for deserialization. processors = GetProcessors(storageType); // 调用processors的OnBeforeDeserialize函数 Invoke_OnBeforeDeserialize(processors, storageType, ref data); Type objectType = storageType; // If the serialized state contains type information, then we need to make sure to update our // objectType and data to the proper values so that when we construct an object instance later // and run deserialization we run it on the proper type. // data是否是dict,并且是否包含有 $type 字段 if (IsTypeSpecified(data)) { fsData typeNameData = data.AsDictionary[Key_InstanceType]; // we wrap everything in a do while false loop so we can break out it do { if (typeNameData.IsString == false) { deserializeResult.AddMessage(Key_InstanceType + " value must be a string (in " + data + ")"); break; } // 取出$type字段的值 string typeName = typeNameData.AsString; //PARADOXNOTION ADDITION // Type type = fsTypeCache.GetType(typeName); //Provide storageType for when last resorting to no Namespace match // 根据typeName,返回类型,(这里处理了泛型和其他类型) Type type = fsTypeCache.GetType(typeName, storageType); if (type == null) { deserializeResult.AddMessage("Unable to locate specified type \"" + typeName + "\""); break; } if (storageType.IsAssignableFrom(type) == false) { deserializeResult.AddMessage("Ignoring type specifier; a field/property of type " + storageType + " cannot hold an instance of " + type); break; } objectType = type; } while (false); } // Construct an object instance if we don't have one already. We also need to construct // an instance if the result type is of the wrong type, which may be the case when we // have a versioned import graph. // 实例化一个实例出来 if (ReferenceEquals(result, null) || result.GetType() != objectType) { result = GetConverter(objectType, overrideConverterType).CreateInstance(data, objectType); } // We call OnBeforeDeserializeAfterInstanceCreation here because we still want to invoke the // method even if the user passed in an existing instance. // 调用processors.OnBeforeDeserializeAfterInstanceCreation Invoke_OnBeforeDeserializeAfterInstanceCreation(processors, storageType, result, ref data); // NOTE: It is critically important that we pass the actual objectType down instead of // using result.GetType() because it is not guaranteed that result.GetType() // will equal objectType, especially because some converters are known to // return dummy values for CreateInstance() (for example, the default behavior // for structs is to just return the type of the struct). return(deserializeResult += InternalDeserialize_4_Cycles(overrideConverterType, data, objectType, ref result)); }
/* //PARADOXNOTION ADDITION * private fsResult InternalSerialize_3_ProcessVersioning(Type overrideConverterType, object instance, out fsData data) { * // note: We do not have to take a Type parameter here, since at this point in the serialization * // algorithm inheritance has *always* been handled. If we took a type parameter, it will * // *always* be equal to instance.GetType(), so why bother taking the parameter? * * // Check to see if there is versioning information for this type. If so, then we need to serialize it. * fsOption<fsVersionedType> optionalVersionedType = fsVersionManager.GetVersionedType(instance.GetType()); * if (optionalVersionedType.HasValue) { * fsVersionedType versionedType = optionalVersionedType.Value; * * // Serialize the actual object content; we'll just wrap it with versioning metadata here. * var result = InternalSerialize_4_Converter(overrideConverterType, instance, out data); * if (result.Failed) return result; * * // Add the versioning information * EnsureDictionary(data); * data.AsDictionary[Key_Version] = new fsData(versionedType.VersionString); * * return result; * } * * // This type has no versioning information -- directly serialize it using the selected converter. * return InternalSerialize_4_Converter(overrideConverterType, instance, out data); * } */ private fsResult InternalSerialize_4_Converter(Type overrideConverterType, object instance, out fsData data) { var instanceType = instance.GetType(); // 这里,就会进入不同的converter的TrySerialize中 return(GetConverter(instanceType, overrideConverterType).TrySerialize(instance, out data, instanceType)); }
private fsResult InternalSerialize_2_Inheritance(Type storageType, Type overrideConverterType, object instance, out fsData data) { // Serialize the actual object with the field type being the same as the object // type so that we won't go into an infinite loop. //var serializeResult = InternalSerialize_3_ProcessVersioning(overrideConverterType, instance, out data); var serializeResult = InternalSerialize_4_Converter(overrideConverterType, instance, out data); if (serializeResult.Failed) { return(serializeResult); } // Do we need to add type information? If the field type and the instance type are different // then we will not be able to recover the correct instance type from the field type when // we deserialize the object. // // Note: We allow converters to request that we do *not* add type information. // 假如storageType != instance.GetType()的话,就需要存储[$type] if (storageType != instance.GetType() && GetConverter(storageType, overrideConverterType).RequestInheritanceSupport(storageType)) { // Add the inheritance metadata,继承的数据 EnsureDictionary(data); data.AsDictionary[Key_InstanceType] = new fsData(instance.GetType().FullName); } return(serializeResult); }
private fsResult InternalSerialize_1_ProcessCycles(Type storageType, Type overrideConverterType, object instance, out fsData data) { // We have an object definition to serialize. try { // Note that we enter the reference group at the beginning of serialization so that we support // references that are at equal serialization levels, not just nested serialization levels, within // the given subobject. A prime example is serialization a list of references. _references.Enter(); // This type does not need cycle support. // 获得instance.GetType()对应的converter var converter = GetConverter(instance.GetType(), overrideConverterType); // 判断是否需要循环,这里是不循环的情况 if (converter.RequestCycleSupport(instance.GetType()) == false) { return(InternalSerialize_2_Inheritance(storageType, overrideConverterType, instance, out data)); } // 当instance IsClass || IsInterface; 才会执行下面的 // We've already serialized this object instance (or it is pending higher up on the call stack). // Just serialize a reference to it to escape the cycle. // // note: We serialize the int as a string to so that we don't lose any information // in a conversion to/from double. // 使用了引用实例的情况,直接返回fsResult.Success if (_references.IsReference(instance)) { // 用Dict创建一个fsData, data = fsData.CreateDictionary(); _lazyReferenceWriter.WriteReference(_references.GetReferenceId(instance), data.AsDictionary); return(fsResult.Success); } // 简单理解为记录instance到_references中 // Mark inside the object graph that we've serialized the instance. We do this *before* // serialization so that if we get back into this function recursively, it'll already // be marked and we can handle the cycle properly without going into an infinite loop. _references.MarkSerialized(instance); // We've created the cycle metadata, so we can now serialize the actual object. // InternalSerialize will handle inheritance correctly for us. var result = InternalSerialize_2_Inheritance(storageType, overrideConverterType, instance, out data); if (result.Failed) { return(result); } _lazyReferenceWriter.WriteDefinition(_references.GetReferenceId(instance), data); return(result); } finally { if (_references.Exit()) { _lazyReferenceWriter.Clear(); } } }
/// <summary> /// Serialize the actual object into the given data storage. /// </summary> /// <param name="instance">The object instance to serialize. This will never be null.</param> /// <param name="serialized">The serialized state.</param> /// <param name="storageType">The field/property type that is storing this instance.</param> /// <returns>If serialization was successful.</returns> public abstract fsResult TrySerialize(object instance, out fsData serialized, Type storageType);
private static void Invoke_OnAfterSerialize(List <fsObjectProcessor> processors, Type storageType, object instance, ref fsData data) { // We run the after calls in reverse order; this significantly reduces the interaction burden between // multiple processors - it makes each one much more independent and ignorant of the other ones. for (int i = processors.Count - 1; i >= 0; --i) { processors[i].OnAfterSerialize(storageType, instance, ref data); } }
/// <summary> /// Deserialize data into the object instance. /// </summary> /// <param name="data">Serialization data to deserialize from.</param> /// <param name="instance">The object instance to deserialize into.</param> /// <param name="storageType">The field/property type that is storing the instance.</param> /// <returns>True if serialization was successful, false otherwise.</returns> public abstract fsResult TryDeserialize(fsData data, ref object instance, Type storageType);
private static void Invoke_OnBeforeDeserialize(List <fsObjectProcessor> processors, Type storageType, ref fsData data) { for (int i = 0; i < processors.Count; ++i) { processors[i].OnBeforeDeserialize(storageType, ref data); } }
protected fsResult CheckKey(fsData data, string key, out fsData subitem) { return(CheckKey(data.AsDictionary, key, out subitem)); }
/// <summary> /// Helper method that simply forwards the call to TrySerialize(typeof(T), instance, out data); /// </summary> public fsResult TrySerialize <T>(T instance, out fsData data) { return(TrySerialize(typeof(T), instance, out data)); }