public override void Serialize(ref T obj, ArchiveMode mode, SerializationStream stream) { var referenceSerialization = stream.Context.Get(ContentSerializerContext.SerializeAttachedReferenceProperty); var contentSerializerContext = stream.Context.Get(ContentSerializerContext.ContentSerializerContextProperty); if (contentSerializerContext != null) { if (mode == ArchiveMode.Serialize) { var contentReference = new ContentReference <T> { Value = obj }; int index = contentSerializerContext.AddContentReference(contentReference); stream.Write(index); } else { int index = stream.ReadInt32(); var contentReference = contentSerializerContext.GetContentReference <T>(index); obj = contentReference.Value; if (obj == null) { // Check if already deserialized var assetReference = contentSerializerContext.AssetManager.FindDeserializedObject(contentReference.Location, typeof(T)); if (assetReference != null) { obj = (T)assetReference.Object; if (obj != null) { contentReference.Value = obj; } } } if (obj == null) { // First time, let's create it obj = (T)AttachedReferenceManager.CreateSerializableVersion(typeof(T), contentReference.Id, contentReference.Location); contentSerializerContext.AssetManager.RegisterDeserializedObject(contentReference.Location, obj); contentReference.Value = obj; } } } else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsNull) { if (mode == ArchiveMode.Deserialize) { obj = default(T); } } else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion) { if (mode == ArchiveMode.Serialize) { // This case will happen when serializing build engine command hashes: we still want Location to still be written var attachedReference = AttachedReferenceManager.GetAttachedReference(obj); if (attachedReference == null || attachedReference.Url == null) { throw new InvalidOperationException("Error when serializing reference."); } // TODO: Do not use string stream.Write(obj.GetType().AssemblyQualifiedName); stream.Write(attachedReference.Id); stream.Write(attachedReference.Url); } else { var type = Type.GetType(stream.ReadString()); var id = stream.Read <Guid>(); var url = stream.ReadString(); obj = (T)AttachedReferenceManager.CreateSerializableVersion(type, id, url); } } else { // This case will happen when serializing build engine command hashes: we still want Location to still be written if (mode == ArchiveMode.Serialize) { // This case will happen when serializing build engine command hashes: we still want Location to still be written var attachedReference = AttachedReferenceManager.GetAttachedReference(obj); if (attachedReference == null || attachedReference.Url == null) { throw new InvalidOperationException("Error when serializing reference."); } stream.Write(attachedReference.Url); } else { // No real case yet throw new NotSupportedException(); } } }
public override void Serialize(ref T obj, ArchiveMode mode, SerializationStream stream) { var referenceSerialization = stream.Context.Get(ContentSerializerContext.SerializeAttachedReferenceProperty); var contentSerializerContext = stream.Context.Get(ContentSerializerContext.ContentSerializerContextProperty); if (contentSerializerContext != null) { if (mode == ArchiveMode.Serialize) { var contentReference = new ContentReference <T>(obj); int index = contentSerializerContext.AddContentReference(contentReference); stream.Write(index); } else { int index = stream.ReadInt32(); var contentReference = contentSerializerContext.GetContentReference <T>(index); obj = contentReference.Value; if (obj == null) { // Check if already deserialized var assetReference = contentSerializerContext.ContentManager.FindDeserializedObject(contentReference.Location, typeof(T)); if (assetReference != null) { obj = (T)assetReference.Object; if (obj != null) { contentReference.Value = obj; } } } if (obj == null && contentSerializerContext.LoadContentReferences) { var contentSerializer = cachedContentSerializer ?? (cachedContentSerializer = contentSerializerContext.ContentManager.Serializer.GetSerializer(null, typeof(T))); if (contentSerializer == null) { // Need to read chunk header to know actual type (note that we can't cache it in cachedContentSerializer as it depends on content) var chunkHeader = contentSerializerContext.ContentManager.ReadChunkHeader(contentReference.Location); if (chunkHeader == null || (contentSerializer = contentSerializerContext.ContentManager.Serializer.GetSerializer(AssemblyRegistry.GetType(chunkHeader.Type), typeof(T))) == null) { throw new InvalidOperationException($"Could not find a valid content serializer for {typeof(T)} when loading {contentReference.Location}"); } } // First time, let's create it if (contentSerializerContext.ContentManager.Exists(contentReference.Location)) { obj = (T)contentSerializer.Construct(contentSerializerContext); contentSerializerContext.ContentManager.RegisterDeserializedObject(contentReference.Location, obj); contentReference.Value = obj; } } } } else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsNull) { if (mode == ArchiveMode.Deserialize) { obj = default(T); } } else if (referenceSerialization == ContentSerializerContext.AttachedReferenceSerialization.AsSerializableVersion) { if (mode == ArchiveMode.Serialize) { // This case will happen when serializing build engine command hashes: we still want Location to still be written var attachedReference = AttachedReferenceManager.GetAttachedReference(obj); if (attachedReference?.Url == null) { throw new InvalidOperationException("Error when serializing reference."); } // TODO: Do not use string stream.Write(obj.GetType().AssemblyQualifiedName); stream.Write(attachedReference.Id); stream.Write(attachedReference.Url); } else { var type = AssemblyRegistry.GetType(stream.ReadString()); var id = stream.Read <Guid>(); var url = stream.ReadString(); obj = (T)AttachedReferenceManager.CreateProxyObject(type, id, url); } } else { // This case will happen when serializing build engine command hashes: we still want Location to still be written if (mode == ArchiveMode.Serialize) { // This case will happen when serializing build engine command hashes: we still want Location to still be written var attachedReference = AttachedReferenceManager.GetAttachedReference(obj); if (attachedReference?.Url == null) { throw new InvalidOperationException("Error when serializing reference."); } stream.Write(attachedReference.Url); } else { // No real case yet throw new NotSupportedException(); } } }