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); }
//... 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); }
//... fsResult Internal_Deserialize(Type overrideConverterType, fsData data, Type storageType, ref object result, out List <fsObjectProcessor> processors) { //$ref encountered. Do before inheritance. if (IsObjectReference(data)) { int refId = int.Parse(data.AsDictionary[KEY_OBJECT_REFERENCE].AsString); result = _references.GetReferenceObject(refId); processors = GetProcessors(result.GetType()); return(fsResult.Success); } 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); Invoke_OnBeforeDeserialize(processors, storageType, ref data); var 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. // $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; } 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); } // invoke callback with storageType Invoke_OnBeforeDeserializeAfterInstanceCreation(processors, storageType, 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]; } // must pass actual objectType instead of storageType return(deserializeResult += converter.TryDeserialize(data, ref result, objectType)); }