/// <summary> /// Adds a new converter that can be used to customize how an object is serialized and /// deserialized. /// </summary> public void AddConverter(fsBaseConverter converter) { if (converter.Serializer != null) { throw new InvalidOperationException("Cannot add a single converter instance to " + "multiple fsConverters -- please construct a new instance for " + converter); } // TODO: wrap inside of a ConverterManager so we can control _converters and _cachedConverters lifetime if (converter is fsDirectConverter) { var directConverter = (fsDirectConverter)converter; _availableDirectConverters[directConverter.ModelType] = directConverter; } else if (converter is fsConverter) { _availableConverters.Insert(0, (fsConverter)converter); } else { throw new InvalidOperationException("Unable to add converter " + converter + "; the type association strategy is unknown. Please use either " + "fsDirectConverter or fsConverter as your base type."); } converter.Serializer = this; // We need to reset our cached converter set, as it could be invalid with the new // converter. Ideally, _cachedConverters should be empty (as the user should fully setup // the serializer before actually using it), but there is no guarantee. _cachedConverters = new Dictionary <Type, fsBaseConverter>(); }
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. fsBaseConverter converter = GetConverter(instance.GetType(), overrideConverterType); if (converter.RequestCycleSupport(instance.GetType()) == false) { return(InternalSerialize_2_Inheritance(storageType, overrideConverterType, instance, out data)); } // 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. if (_references.IsReference(instance)) { data = fsData.CreateDictionary(); _lazyReferenceWriter.WriteReference(_references.GetReferenceId(instance), data.AsDictionary); return(fsResult.Success); } // 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. fsResult 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(); } } }