Example #1
0
        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);
        }
Example #2
0
        //...
        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);
        }
Example #3
0
        //...
        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));
        }