/* Copyright 2010 10gen Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; namespace MongoDB.Bson.DefaultSerializer { public static class EnumerableSerializerRegistration { #region public static methods public static void RegisterGenericSerializerDefinitions() { BsonSerializer.RegisterGenericSerializerDefinition(typeof(HashSet<>), typeof(EnumerableSerializer<>)); BsonSerializer.RegisterGenericSerializerDefinition(typeof(ICollection<>), typeof(EnumerableSerializer<>)); BsonSerializer.RegisterGenericSerializerDefinition(typeof(IEnumerable<>), typeof(EnumerableSerializer<>)); BsonSerializer.RegisterGenericSerializerDefinition(typeof(IList<>), typeof(EnumerableSerializer<>)); BsonSerializer.RegisterGenericSerializerDefinition(typeof(List<>), typeof(EnumerableSerializer<>)); BsonSerializer.RegisterGenericSerializerDefinition(typeof(LinkedList<>), typeof(EnumerableSerializer<>)); } #endregion } public class EnumerableSerializer : BsonBaseSerializer { #region constructors public EnumerableSerializer() { } public EnumerableSerializer( object serializationOptions ) { } #endregion #region public methods public override object Deserialize( BsonReader bsonReader, Type nominalType ) { var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Array) { bsonReader.ReadStartArray(); var list = (nominalType == typeof(List) || nominalType.IsInterface) ? new List() : (ICollection) Activator.CreateInstance(nominalType); var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(T)); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { bsonReader.SkipName(); var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(T)); var serializer = BsonSerializer.LookupSerializer(elementType); var element = (T) serializer.Deserialize(bsonReader, typeof(T)); list.Add(element); } bsonReader.ReadEndArray(); return list; } else { var message = string.Format("Can't deserialize a {0} from BsonType {1}", nominalType.FullName, bsonType); throw new FileFormatException(message); } } public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, bool serializeIdFirst ) { if (value == null) { bsonWriter.WriteNull(); } else { bsonWriter.WriteStartArray(); int index = 0; foreach (var element in (IEnumerable) value) { bsonWriter.WriteName(index.ToString()); BsonSerializer.Serialize(bsonWriter, typeof(T), element); index++; } bsonWriter.WriteEndArray(); } } #endregion } public static class QueueSerializerRegistration { #region public static methods public static void RegisterGenericSerializerDefinitions() { BsonSerializer.RegisterGenericSerializerDefinition(typeof(Queue<>), typeof(QueueSerializer<>)); } #endregion } public class QueueSerializer : BsonBaseSerializer { #region constructors public QueueSerializer( object serializationOptions ) { } #endregion #region public methods public override object Deserialize( BsonReader bsonReader, Type nominalType ) { var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Array) { bsonReader.ReadStartArray(); var queue = new Queue(); var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(T)); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { bsonReader.SkipName(); var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(T)); var serializer = BsonSerializer.LookupSerializer(elementType); var element = (T) serializer.Deserialize(bsonReader, typeof(T)); queue.Enqueue(element); } bsonReader.ReadEndArray(); return queue; } else { var message = string.Format("Can't deserialize a {0} from BsonType {1}", nominalType.FullName, bsonType); throw new FileFormatException(message); } } public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, bool serializeIdFirst ) { if (value == null) { bsonWriter.WriteNull(); } else { bsonWriter.WriteStartArray(); int index = 0; foreach (var element in (Queue) value) { bsonWriter.WriteName(index.ToString()); BsonSerializer.Serialize(bsonWriter, typeof(T), element); index++; } bsonWriter.WriteEndArray(); } } #endregion } public static class StackSerializerRegistration { #region public static methods public static void RegisterGenericSerializerDefinitions() { BsonSerializer.RegisterGenericSerializerDefinition(typeof(Stack<>), typeof(StackSerializer<>)); } #endregion } public class StackSerializer : BsonBaseSerializer { #region constructors public StackSerializer( object serializationOptions ) { } #endregion #region public methods public override object Deserialize( BsonReader bsonReader, Type nominalType ) { var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Array) { bsonReader.ReadStartArray(); var stack = new Stack(); var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(T)); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { bsonReader.SkipName(); var elementType = discriminatorConvention.GetActualType(bsonReader, typeof(T)); var serializer = BsonSerializer.LookupSerializer(elementType); var element = (T) serializer.Deserialize(bsonReader, typeof(T)); stack.Push(element); } bsonReader.ReadEndArray(); return stack; } else { var message = string.Format("Can't deserialize a {0} from BsonType {1}", nominalType.FullName, bsonType); throw new FileFormatException(message); } } public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, bool serializeIdFirst ) { if (value == null) { bsonWriter.WriteNull(); } else { bsonWriter.WriteStartArray(); var outputOrder = new List((Stack) value); // serialize first pushed item first (reverse of enumerator order) outputOrder.Reverse(); int index = 0; foreach (var element in outputOrder) { bsonWriter.WriteName(index.ToString()); BsonSerializer.Serialize(bsonWriter, typeof(T), element); index++; } bsonWriter.WriteEndArray(); } } #endregion } }