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

        /// Serialize the given value.
        public fsResult TrySerialize(Type storageType, object instance, out fsData data)
        {
            return(TrySerialize(storageType, instance, out data, null));
        }
Example #4
0
        ///----------------------------------------------------------------------------------------------

        /// 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));
        }
Example #5
0
        /// <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);
        }
Example #6
0
 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));
 }
Example #9
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 #10
0
/*      //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));
        }
Example #11
0
/*      //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));
        }
Example #12
0
        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);
        }
Example #13
0
        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);
Example #15
0
 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);
Example #17
0
 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));
 }
Example #19
0
 /// <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));
 }