/// <summary> /// Gets the serialization info for a member. /// </summary> /// <param name="memberName">The member name.</param> /// <returns>The serialization info for the member.</returns> public BsonSerializationInfo GetMemberSerializationInfo(string memberName) { foreach (var memberMap in _classMap.AllMemberMaps) { if (memberMap.MemberName == memberName) { var elementName = memberMap.ElementName; var serializer = memberMap.GetSerializer(memberMap.MemberType); var nominalType = memberMap.MemberType; var serializationOptions = memberMap.SerializationOptions; return(new BsonSerializationInfo(elementName, serializer, nominalType, serializationOptions)); } } var message = string.Format( "Class {0} does not have a member called {1}.", BsonUtils.GetFriendlyTypeName(_classMap.ClassType), memberName); throw new ArgumentOutOfRangeException("memberName", message); }
// public methods /// <summary> /// Applies a modification to the member map. /// </summary> /// <param name="memberMap">The member map.</param> public virtual void Apply(BsonMemberMap memberMap) { var memberSerializer = memberMap.GetSerializer(memberMap.MemberType); var memberSerializationOptions = memberMap.SerializationOptions; if (memberSerializationOptions == null) { var memberDefaultSerializationOptions = memberSerializer.GetDefaultSerializationOptions(); if (memberDefaultSerializationOptions == null) { var message = string.Format( "A serialization options attribute of type {0} cannot be used when the serializer is of type {1}.", BsonUtils.GetFriendlyTypeName(this.GetType()), BsonUtils.GetFriendlyTypeName(memberSerializer.GetType())); throw new NotSupportedException(message); } memberSerializationOptions = memberDefaultSerializationOptions.Clone(); memberMap.SetSerializationOptions(memberSerializationOptions); } memberSerializationOptions.ApplyAttribute(memberSerializer, this); }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { var keyValuePair = (KeyValuePair <TKey, TValue>)value; var keyValuePairSerializationOptions = EnsureSerializationOptions <KeyValuePairSerializationOptions>(options); var keyType = (keyValuePair.Key == null) ? typeof(TKey) : keyValuePair.Key.GetType(); var keySerializer = GetKeySerializer(keyType); var valueType = (keyValuePair.Value == null) ? typeof(TValue) : keyValuePair.Value.GetType(); var valueSerializer = GetValueSerializer(valueType); switch (keyValuePairSerializationOptions.Representation) { case BsonType.Array: bsonWriter.WriteStartArray(); keySerializer.Serialize(bsonWriter, typeof(TKey), keyValuePair.Key, keyValuePairSerializationOptions.KeySerializationOptions); valueSerializer.Serialize(bsonWriter, typeof(TValue), keyValuePair.Value, keyValuePairSerializationOptions.ValueSerializationOptions); bsonWriter.WriteEndArray(); break; case BsonType.Document: bsonWriter.WriteStartDocument(); bsonWriter.WriteName("k"); keySerializer.Serialize(bsonWriter, typeof(TKey), keyValuePair.Key, keyValuePairSerializationOptions.KeySerializationOptions); bsonWriter.WriteName("v"); valueSerializer.Serialize(bsonWriter, typeof(TValue), keyValuePair.Value, keyValuePairSerializationOptions.ValueSerializationOptions); bsonWriter.WriteEndDocument(); break; default: var message = string.Format( "'{0}' is not a valid {1} representation.", keyValuePairSerializationOptions.Representation, BsonUtils.GetFriendlyTypeName(typeof(KeyValuePair <TKey, TValue>))); throw new BsonSerializationException(message); } }
/// <summary> /// Serializes a value. /// </summary> /// <param name="context">The serialization context.</param> /// <param name="args">The serialization args.</param> /// <param name="value">The object.</param> public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value) { if (value == null) { var message = string.Format( "C# null values of type '{0}' cannot be serialized using a serializer of type '{1}'.", BsonUtils.GetFriendlyTypeName(ValueType), BsonUtils.GetFriendlyTypeName(GetType())); throw new BsonSerializationException(message); } var actualType = value.GetType(); if (actualType != ValueType && !args.SerializeAsNominalType) { var serializer = BsonSerializer.LookupSerializer(actualType); serializer.Serialize(context, value); return; } SerializeValue(context, args, value); }
// private methods private IDictionary CreateInstance(Type type) { if (type.IsInterface) { // in the case of an interface pick a reasonable class that implements that interface if (type == typeof(IDictionary)) { return(new Hashtable()); } } else { if (type == typeof(Hashtable)) { return(new Hashtable()); } else if (type == typeof(ListDictionary)) { return(new ListDictionary()); } else if (type == typeof(OrderedDictionary)) { return(new OrderedDictionary()); } else if (type == typeof(SortedList)) { return(new SortedList()); } else if (typeof(IDictionary).IsAssignableFrom(type)) { return((IDictionary)Activator.CreateInstance(type)); } } var message = string.Format("DictionarySerializer can't be used with type {0}.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); }
// private methods private IDictionary <TKey, TValue> CreateInstance(Type type) { if (type.IsInterface) { // in the case of an interface pick a reasonable class that implements that interface if (type == typeof(IDictionary <TKey, TValue>)) { return(new Dictionary <TKey, TValue>()); } } else { if (type == typeof(Dictionary <TKey, TValue>)) { return(new Dictionary <TKey, TValue>()); } else if (type == typeof(SortedDictionary <TKey, TValue>)) { return(new SortedDictionary <TKey, TValue>()); } else if (type == typeof(SortedList <TKey, TValue>)) { return(new SortedList <TKey, TValue>()); } else if (typeof(IDictionary <TKey, TValue>).IsAssignableFrom(type)) { return((IDictionary <TKey, TValue>)Activator.CreateInstance(type)); } } var message = string.Format("DictionarySerializer<{0}, {1}> can't be used with type {1}.", BsonUtils.GetFriendlyTypeName(typeof(TKey)), BsonUtils.GetFriendlyTypeName(typeof(TValue)), BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); }
/// <inheritdoc/> public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { if (type == null) { throw new ArgumentNullException("type"); } if (type.IsGenericType && type.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } Type serializerType; if (__serializerTypes.TryGetValue(type, out serializerType)) { return(CreateSerializer(serializerType, serializerRegistry)); } if (type.IsGenericType && !type.ContainsGenericParameters) { Type serializerTypeDefinition; if (__serializerTypes.TryGetValue(type.GetGenericTypeDefinition(), out serializerTypeDefinition)) { return(CreateGenericSerializer(serializerTypeDefinition, type.GetGenericArguments(), serializerRegistry)); } } if (type.IsArray) { var elementType = type.GetElementType(); switch (type.GetArrayRank()) { case 1: var arraySerializerDefinition = typeof(ArraySerializer <>); return(CreateGenericSerializer(arraySerializerDefinition, new[] { elementType }, serializerRegistry)); case 2: var twoDimensionalArraySerializerDefinition = typeof(TwoDimensionalArraySerializer <>); return(CreateGenericSerializer(twoDimensionalArraySerializerDefinition, new[] { elementType }, serializerRegistry)); case 3: var threeDimensionalArraySerializerDefinition = typeof(ThreeDimensionalArraySerializer <>); return(CreateGenericSerializer(threeDimensionalArraySerializerDefinition, new[] { elementType }, serializerRegistry)); default: var message = string.Format("No serializer found for array for rank {0}.", type.GetArrayRank()); throw new BsonSerializationException(message); } } return(GetCollectionSerializer(type, serializerRegistry)); }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public override void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { if (nominalType == typeof(object)) { var actualType = value.GetType(); bsonWriter.WriteStartDocument(); bsonWriter.WriteString("_t", TypeNameDiscriminator.GetDiscriminator(actualType)); bsonWriter.WriteName("_v"); Serialize(bsonWriter, actualType, value, options); // recursive call replacing nominalType with actualType bsonWriter.WriteEndDocument(); return; } var dictionary = (IDictionary <TKey, TValue>)value; var dictionarySerializationOptions = EnsureSerializationOptions(options); var dictionaryRepresentation = dictionarySerializationOptions.Representation; var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions; if (dictionaryRepresentation == DictionaryRepresentation.Dynamic) { if (typeof(TKey) == typeof(string) || typeof(TKey) == typeof(object)) { dictionaryRepresentation = DictionaryRepresentation.Document; foreach (object key in dictionary.Keys) { var name = key as string; // key might not be a string if (string.IsNullOrEmpty(name) || name[0] == '$' || name.IndexOf('.') != -1 || name.IndexOf('\0') != -1) { dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays; break; } } } else { dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays; } } switch (dictionaryRepresentation) { case DictionaryRepresentation.Document: bsonWriter.WriteStartDocument(); foreach (var keyValuePair in dictionary) { bsonWriter.WriteName((string)(object)keyValuePair.Key); BsonSerializer.Serialize(bsonWriter, typeof(TValue), keyValuePair.Value, keyValuePairSerializationOptions.ValueSerializationOptions); } bsonWriter.WriteEndDocument(); break; case DictionaryRepresentation.ArrayOfArrays: case DictionaryRepresentation.ArrayOfDocuments: // override KeyValuePair representation if necessary var keyValuePairRepresentation = (dictionaryRepresentation == DictionaryRepresentation.ArrayOfArrays) ? BsonType.Array : BsonType.Document; if (keyValuePairSerializationOptions.Representation != keyValuePairRepresentation) { keyValuePairSerializationOptions = new KeyValuePairSerializationOptions( keyValuePairRepresentation, keyValuePairSerializationOptions.KeySerializationOptions, keyValuePairSerializationOptions.ValueSerializationOptions); } bsonWriter.WriteStartArray(); foreach (var keyValuePair in dictionary) { _keyValuePairSerializer.Serialize( bsonWriter, typeof(KeyValuePair <TKey, TValue>), keyValuePair, keyValuePairSerializationOptions); } bsonWriter.WriteEndArray(); break; default: var message = string.Format("'{0}' is not a valid IDictionary<{1}, {2}> representation.", dictionaryRepresentation, BsonUtils.GetFriendlyTypeName(typeof(TKey)), BsonUtils.GetFriendlyTypeName(typeof(TValue))); throw new BsonSerializationException(message); } } }
/*******************************************/ public override CustomObject Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; var bsonType = bsonReader.CurrentBsonType; if (bsonReader.State != BsonReaderState.Type) { bsonType = bsonReader.GetCurrentBsonType(); } string message; switch (bsonType) { case BsonType.Document: var dynamicContext = context.With(ConfigureDeserializationContext); bsonReader.ReadStartDocument(); CustomObject document = new CustomObject(); Dictionary <string, object> dic = document.CustomData; while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); var value = m_ObjectSerializer.Deserialize(dynamicContext); switch (name) { case "Name": document.Name = value as string; break; case "Tags": document.Tags = new HashSet <string>(((List <object>)value).Cast <string>()); break; case "BHoM_Guid": document.BHoM_Guid = new Guid(value as string); break; case "CustomData": while (value is CustomObject) { value = ((CustomObject)value).CustomData; } if (value is Dictionary <string, object> ) { Dictionary <string, object> customData = value as Dictionary <string, object>; if (customData.Count > 0) { dic["AdditionalData"] = value; } } break; default: dic[name] = value; break; } } bsonReader.ReadEndDocument(); return(document); default: message = string.Format("Cannot deserialize a '{0}' from BsonType '{1}'.", BsonUtils.GetFriendlyTypeName(typeof(CustomObject)), bsonType); throw new FormatException(message); } }
/// <inheritdoc/> public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { if (type == null) { throw new ArgumentNullException("type"); } var typeInfo = type.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } Type serializerType; if (__serializersTypes.TryGetValue(type, out serializerType)) { return(CreateSerializer(serializerType, serializerRegistry)); } if (typeInfo.IsGenericType && !typeInfo.ContainsGenericParameters) { Type serializerTypeDefinition; if (__serializersTypes.TryGetValue(type.GetGenericTypeDefinition(), out serializerTypeDefinition)) { return(CreateGenericSerializer(serializerTypeDefinition, typeInfo.GetGenericArguments(), serializerRegistry)); } } if (typeInfo.IsEnum) { return(CreateGenericSerializer(typeof(EnumSerializer <>), new[] { type }, serializerRegistry)); } return(null); }
private void TranslateOfType(MethodCallExpression methodCallExpression) { var method = methodCallExpression.Method; if (method.DeclaringType != typeof(Queryable)) { var message = string.Format("OfType method of class {0} is not supported.", BsonUtils.GetFriendlyTypeName(method.DeclaringType)); throw new NotSupportedException(message); } if (!method.IsStatic) { throw new NotSupportedException("Expected OfType to be a static method."); } if (!method.IsGenericMethod) { throw new NotSupportedException("Expected OfType to be a generic method."); } var actualType = method.GetGenericArguments()[0]; var args = methodCallExpression.Arguments.ToArray(); if (args.Length != 1) { throw new NotSupportedException("Expected OfType method to have a single argument."); } var sourceExpression = args[0]; if (!sourceExpression.Type.IsGenericType) { throw new NotSupportedException("Expected source argument to OfType to be a generic type."); } var nominalType = sourceExpression.Type.GetGenericArguments()[0]; if (_projection != null) { throw new NotSupportedException("OfType after a projection is not supported."); } var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(nominalType); var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType); if (discriminator == null) { return; // nothing to do } if (discriminator.IsBsonArray) { discriminator = discriminator.AsBsonArray[discriminator.AsBsonArray.Count - 1]; } var query = Query.EQ(discriminatorConvention.ElementName, discriminator); var injectMethodInfo = typeof(LinqToMongo).GetMethod("Inject"); var body = Expression.Call(injectMethodInfo, Expression.Constant(query)); var parameter = Expression.Parameter(nominalType, "x"); var predicate = Expression.Lambda(body, parameter); CombinePredicateWithWhereClause(methodCallExpression, predicate); _ofType = actualType; }
// private methods private ICollection <T> CreateInstance(Type type) { string message; if (type.IsInterface) { // in the case of an interface pick a reasonable class that implements that interface if (type == typeof(IEnumerable <T>) || type == typeof(ICollection <T>) || type == typeof(IList <T>)) { return(new List <T>()); } } else { if (type == typeof(List <T>)) { return(new List <T>()); } else if (typeof(IEnumerable <T>).IsAssignableFrom(type)) { var instance = (IEnumerable <T>)Activator.CreateInstance(type); var collection = instance as ICollection <T>; if (collection == null) { message = string.Format("Enumerable class {0} does not implement ICollection<T> so it can't be deserialized.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } return(collection); } } message = string.Format("EnumerableSerializer<{0}> can't be used with type {1}.", BsonUtils.GetFriendlyTypeName(typeof(T)), BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); }
/// <summary> /// Serializes an object to a BsonWriter. /// </summary> /// <param name="bsonWriter">The BsonWriter.</param> /// <param name="nominalType">The nominal type.</param> /// <param name="value">The object.</param> /// <param name="options">The serialization options.</param> public void Serialize( BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) { if (value == null) { bsonWriter.WriteNull(); } else { // Nullable types are weird because they get boxed as their underlying value type // we can best handle that by switching the nominalType to the underlying value type // (so VerifyNominalType doesn't fail and we don't get an unnecessary discriminator) if (nominalType.IsGenericType && nominalType.GetGenericTypeDefinition() == typeof(Nullable <>)) { nominalType = nominalType.GetGenericArguments()[0]; } VerifyNominalType(nominalType); var actualType = (value == null) ? nominalType : value.GetType(); if (actualType != _classMap.ClassType) { var message = string.Format("BsonClassMapSerializer.Serialize for type {0} was called with actualType {1}.", BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType)); throw new BsonSerializationException(message); } var documentSerializationOptions = (options ?? DocumentSerializationOptions.Defaults) as DocumentSerializationOptions; if (documentSerializationOptions == null) { var message = string.Format( "Serializer BsonClassMapSerializer expected serialization options of type {0}, not {1}.", BsonUtils.GetFriendlyTypeName(typeof(DocumentSerializationOptions)), BsonUtils.GetFriendlyTypeName(options.GetType())); throw new BsonSerializationException(message); } bsonWriter.WriteStartDocument(); BsonMemberMap idMemberMap = null; if (documentSerializationOptions.SerializeIdFirst) { idMemberMap = _classMap.IdMemberMap; if (idMemberMap != null) { SerializeMember(bsonWriter, value, idMemberMap); } } if (actualType != nominalType || _classMap.DiscriminatorIsRequired || _classMap.HasRootClass) { // never write out a discriminator for an anonymous class if (!_classMap.IsAnonymous) { var discriminatorConvention = _classMap.GetDiscriminatorConvention(); var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType); if (discriminator != null) { bsonWriter.WriteName(discriminatorConvention.ElementName); BsonValueSerializer.Instance.Serialize(bsonWriter, typeof(BsonValue), discriminator, null); } } } var allMemberMaps = _classMap.AllMemberMaps; var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex; for (var memberMapIndex = 0; memberMapIndex < allMemberMaps.Count; ++memberMapIndex) { var memberMap = allMemberMaps[memberMapIndex]; // note: if serializeIdFirst is false then idMemberMap will be null (so no property will be skipped) if (memberMap != idMemberMap) { if (memberMapIndex != extraElementsMemberMapIndex) { SerializeMember(bsonWriter, value, memberMap); } else { SerializeExtraElements(bsonWriter, value, memberMap); } } } bsonWriter.WriteEndDocument(); } }
// public methods /// <summary> /// Deserializes a value. /// </summary> /// <param name="context">The deserialization context.</param> /// <param name="args">The deserialization args.</param> /// <returns>A deserialized value.</returns> public override T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; var bsonType = bsonReader.GetCurrentBsonType(); string message; switch (bsonType) { case BsonType.Document: var dynamicContext = context.With(ConfigureDeserializationContext); bsonReader.ReadStartDocument(); var document = CreateDocument(); while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); var value = _objectSerializer.Deserialize(dynamicContext); SetValueForMember(document, name, value); } bsonReader.ReadEndDocument(); return(document); case BsonType.Null: bsonReader.ReadNull(); return(null); default: message = string.Format("Cannot deserialize a '{0}' from BsonType '{1}'.", BsonUtils.GetFriendlyTypeName(typeof(T)), bsonType); throw new FormatException(message); } }
// public methods /// <summary> /// Apply an attribute to these serialization options and modify the options accordingly. /// </summary> /// <param name="serializer">The serializer that these serialization options are for.</param> /// <param name="attribute">The serialization options attribute.</param> public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute) { EnsureNotFrozen(); var representationAttribute = attribute as BsonRepresentationAttribute; if (representationAttribute != null) { _allowOverflow = representationAttribute.AllowOverflow; _allowTruncation = representationAttribute.AllowTruncation; _representation = representationAttribute.Representation; return; } var message = string.Format("A serialization options attribute of type {0} cannot be applied to serialization options of type {1}.", BsonUtils.GetFriendlyTypeName(attribute.GetType()), BsonUtils.GetFriendlyTypeName(GetType())); throw new NotSupportedException(message); }
/// <summary> /// Registers a serializer for a type. /// </summary> /// <param name="type">The type.</param> /// <param name="serializer">The serializer.</param> public static void RegisterSerializer(Type type, IBsonSerializer serializer) { // don't allow a serializer to be registered for subclasses of BsonValue if (typeof(BsonValue).IsAssignableFrom(type)) { var message = string.Format("A serializer cannot be registered for type {0} because it is a subclass of BsonValue.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } __configLock.EnterWriteLock(); try { if (__serializers.ContainsKey(type)) { var message = string.Format("There is already a serializer registered for type {0}.", type.FullName); throw new BsonSerializationException(message); } __serializers.Add(type, serializer); } finally { __configLock.ExitWriteLock(); } }
/// <inheritdoc/> public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { if (type == null) { throw new ArgumentNullException("type"); } var typeInfo = type.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } if ((typeInfo.IsClass || (typeInfo.IsValueType && !typeInfo.IsPrimitive)) && !typeof(Array).IsAssignableFrom(type) && !typeof(Enum).IsAssignableFrom(type)) { var classMap = BsonClassMap.LookupClassMap(type); var classMapSerializerDefinition = typeof(BsonClassMapSerializer <>); var classMapSerializerType = classMapSerializerDefinition.MakeGenericType(type); return((IBsonSerializer)Activator.CreateInstance(classMapSerializerType, classMap)); } return(null); }
/// <summary> /// Registers the serializer mapping. /// </summary> /// <param name="type">The type.</param> /// <param name="serializerType">Type of the serializer.</param> public void RegisterMapping(Type type, Type serializerType) { if (type == null) { throw new ArgumentNullException("type"); } if (serializerType == null) { throw new ArgumentNullException("serializerType"); } var typeInfo = type.GetTypeInfo(); var serializerTypeInfo = serializerType.GetTypeInfo(); if (typeInfo.ContainsGenericParameters != serializerTypeInfo.ContainsGenericParameters) { throw new ArgumentException("The type and the serializerType must have the same number of type parameters."); } if (typeInfo.ContainsGenericParameters) { if (!typeInfo.IsGenericTypeDefinition || !serializerTypeInfo.IsGenericTypeDefinition) { throw new ArgumentException("A generic type must either have all or none of the type parameters assigned."); } if (type.GetTypeInfo().GetGenericArguments().Length != serializerType.GetTypeInfo().GetGenericArguments().Length) { throw new ArgumentException("The type and the serializerType must have the same number of type parameters."); } } if (!_serializerTypes.TryAdd(type, serializerType)) { var message = string.Format("There is already a serializer mapping registered for type {0}.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } }
private void TranslateWithIndex(MethodCallExpression methodCallExpression) { if (methodCallExpression.Arguments.Count != 2) { throw new ArgumentOutOfRangeException("methodCallExpression"); } var method = methodCallExpression.Method; if (method.DeclaringType != typeof(LinqToMongo)) { var message = string.Format("WithIndex method of class {0} is not supported.", BsonUtils.GetFriendlyTypeName(method.DeclaringType)); throw new NotSupportedException(message); } if (_indexHint != null) { throw new NotSupportedException("Only one index can be used for each query"); } if (_distinct != null) { var message = "WithIndex cannot be used together with Distinct."; throw new NotSupportedException(message); } Expression expression = methodCallExpression.Arguments[1]; if (expression.Type != typeof(BsonString) && expression.Type != typeof(BsonDocument)) { throw new ArgumentOutOfRangeException("methodCallExpression", "Expected an Expression of Type BsonString or BsonDocument."); } var constantExpression = expression as ConstantExpression; if (constantExpression == null) { throw new ArgumentOutOfRangeException("methodCallExpression", "Expected a ConstantExpression."); } _indexHint = (BsonValue)constantExpression.Value; }
/// <summary> /// Deserializes an object from a BsonReader. /// </summary> /// <param name="bsonReader">The BsonReader.</param> /// <param name="nominalType">The nominal type of the object.</param> /// <param name="actualType">The actual type of the object.</param> /// <param name="options">The serialization options.</param> /// <returns>An object.</returns> public object Deserialize( BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) { VerifyNominalType(nominalType); var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == Bson.BsonType.Null) { bsonReader.ReadNull(); return(null); } else { if (actualType != _classMap.ClassType) { var message = string.Format("BsonClassMapSerializer.Deserialize for type {0} was called with actualType {1}.", BsonUtils.GetFriendlyTypeName(_classMap.ClassType), BsonUtils.GetFriendlyTypeName(actualType)); throw new BsonSerializationException(message); } if (actualType.IsValueType) { var message = string.Format("Value class {0} cannot be deserialized.", actualType.FullName); throw new BsonSerializationException(message); } if (_classMap.IsAnonymous) { throw new InvalidOperationException("An anonymous class cannot be deserialized."); } if (bsonType != BsonType.Document) { var message = string.Format( "Expected a nested document representing the serialized form of a {0} value, but found a value of type {1} instead.", actualType.FullName, bsonType); throw new FileFormatException(message); } Dictionary <string, object> values = null; object obj = null; ISupportInitialize supportsInitialization = null; if (_classMap.HasCreatorMaps) { // for creator-based deserialization we first gather the values in a dictionary and then call a matching creator values = new Dictionary <string, object>(); } else { // for mutable classes we deserialize the values directly into the result object obj = _classMap.CreateInstance(); supportsInitialization = obj as ISupportInitialize; if (supportsInitialization != null) { supportsInitialization.BeginInit(); } } var discriminatorConvention = _classMap.GetDiscriminatorConvention(); var allMemberMaps = _classMap.AllMemberMaps; var extraElementsMemberMapIndex = _classMap.ExtraElementsMemberMapIndex; var memberMapBitArray = FastMemberMapHelper.GetBitArray(allMemberMaps.Count); bsonReader.ReadStartDocument(); var elementTrie = _classMap.ElementTrie; bool memberMapFound; int memberMapIndex; while (bsonReader.ReadBsonType(elementTrie, out memberMapFound, out memberMapIndex) != BsonType.EndOfDocument) { var elementName = bsonReader.ReadName(); if (memberMapFound) { var memberMap = allMemberMaps[memberMapIndex]; if (memberMapIndex != extraElementsMemberMapIndex) { if (obj != null) { if (memberMap.IsReadOnly) { bsonReader.SkipValue(); } else { var value = DeserializeMemberValue(bsonReader, memberMap); memberMap.Setter(obj, value); } } else { var value = DeserializeMemberValue(bsonReader, memberMap); values[elementName] = value; } } else { DeserializeExtraElement(bsonReader, obj, elementName, memberMap); } memberMapBitArray[memberMapIndex >> 5] |= 1U << (memberMapIndex & 31); } else { if (elementName == discriminatorConvention.ElementName) { bsonReader.SkipValue(); // skip over discriminator continue; } if (extraElementsMemberMapIndex >= 0) { DeserializeExtraElement(bsonReader, obj, elementName, _classMap.ExtraElementsMemberMap); memberMapBitArray[extraElementsMemberMapIndex >> 5] |= 1U << (extraElementsMemberMapIndex & 31); } else if (_classMap.IgnoreExtraElements) { bsonReader.SkipValue(); } else { var message = string.Format( "Element '{0}' does not match any field or property of class {1}.", elementName, _classMap.ClassType.FullName); throw new FileFormatException(message); } } } bsonReader.ReadEndDocument(); // check any members left over that we didn't have elements for (in blocks of 32 elements at a time) for (var bitArrayIndex = 0; bitArrayIndex < memberMapBitArray.Length; ++bitArrayIndex) { memberMapIndex = bitArrayIndex << 5; var memberMapBlock = ~memberMapBitArray[bitArrayIndex]; // notice that bits are flipped so 1's are now the missing elements // work through this memberMapBlock of 32 elements while (true) { // examine missing elements (memberMapBlock is shifted right as we work through the block) for (; (memberMapBlock & 1) != 0; ++memberMapIndex, memberMapBlock >>= 1) { var memberMap = allMemberMaps[memberMapIndex]; if (memberMap.IsReadOnly) { continue; } if (memberMap.IsRequired) { var fieldOrProperty = (memberMap.MemberInfo.MemberType == MemberTypes.Field) ? "field" : "property"; var message = string.Format( "Required element '{0}' for {1} '{2}' of class {3} is missing.", memberMap.ElementName, fieldOrProperty, memberMap.MemberName, _classMap.ClassType.FullName); throw new FileFormatException(message); } if (obj != null) { memberMap.ApplyDefaultValue(obj); } else if (memberMap.IsDefaultValueSpecified && !memberMap.IsReadOnly) { values[memberMap.ElementName] = memberMap.DefaultValue; } } if (memberMapBlock == 0) { break; } // skip ahead to the next missing element var leastSignificantBit = FastMemberMapHelper.GetLeastSignificantBit(memberMapBlock); memberMapIndex += leastSignificantBit; memberMapBlock >>= leastSignificantBit; } } if (obj != null) { if (supportsInitialization != null) { supportsInitialization.EndInit(); } return(obj); } else { return(CreateInstanceUsingCreator(values)); } } }
// private methods private ReadOnlyCollection <T> CreateInstance(Type type, IList <T> list) { if (type == typeof(ReadOnlyCollection <T>)) { return(new ReadOnlyCollection <T>(list)); } else if (typeof(ReadOnlyCollection <T>).IsAssignableFrom(type)) { return((ReadOnlyCollection <T>)Activator.CreateInstance(type, list)); } var message = string.Format("ReadOnlyCollectionSerializer<{0}> can't be used with type {1}.", BsonUtils.GetFriendlyTypeName(typeof(T)), BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); }
public override IAggregateFluent <TNewResult> OfType <TNewResult>(IBsonSerializer <TNewResult> newResultSerializer) { var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(typeof(TResult)); if (discriminatorConvention == null) { var message = string.Format("OfType requires that a discriminator convention exist for type: {0}.", BsonUtils.GetFriendlyTypeName(typeof(TResult))); throw new NotSupportedException(message); } var discriminatorValue = discriminatorConvention.GetDiscriminator(typeof(TResult), typeof(TNewResult)); var ofTypeFilter = new BsonDocument(discriminatorConvention.ElementName, discriminatorValue); const string operatorName = "$match"; var stage = new DelegatedPipelineStageDefinition <TResult, TNewResult>( operatorName, (s, sr) => { return(new RenderedPipelineStageDefinition <TNewResult>( operatorName, new BsonDocument(operatorName, ofTypeFilter), newResultSerializer ?? (s as IBsonSerializer <TNewResult>) ?? sr.GetSerializer <TNewResult>())); }); return(AppendStage <TNewResult>(stage)); }
// public methods /// <summary> /// Apply an attribute to these serialization options and modify the options accordingly. /// </summary> /// <param name="serializer">The serializer that these serialization options are for.</param> /// <param name="attribute">The serialization options attribute.</param> public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute) { EnsureNotFrozen(); var dateTimeSerializationOptionsAttribute = attribute as BsonDateTimeOptionsAttribute; if (dateTimeSerializationOptionsAttribute != null) { _dateOnly = dateTimeSerializationOptionsAttribute.DateOnly; _kind = dateTimeSerializationOptionsAttribute.Kind; _representation = dateTimeSerializationOptionsAttribute.Representation; return; } var message = string.Format("A serialization options attribute of type {0} cannot be applied to serialization options of type {1}.", BsonUtils.GetFriendlyTypeName(attribute.GetType()), BsonUtils.GetFriendlyTypeName(GetType())); throw new NotSupportedException(message); }
// public methods /// <summary> /// Apply an attribute to these serialization options and modify the options accordingly. /// </summary> /// <param name="serializer">The serializer that these serialization options are for.</param> /// <param name="attribute">The serialization options attribute.</param> public override void ApplyAttribute(IBsonSerializer serializer, Attribute attribute) { EnsureNotFrozen(); var dictionaryOptionsAttribute = attribute as BsonDictionaryOptionsAttribute; if (dictionaryOptionsAttribute != null) { _representation = dictionaryOptionsAttribute.Representation; return; } // for backward compatibility reasons representations Array and Document apply to the Dictionary and not the values var representationAttribute = attribute as BsonRepresentationAttribute; if (representationAttribute != null) { switch (representationAttribute.Representation) { case BsonType.Array: _representation = DictionaryRepresentation.ArrayOfArrays; return; case BsonType.Document: _representation = DictionaryRepresentation.Document; return; } } // any other attributes are applied to the values var valueType = typeof(object); if (serializer.GetType().IsGenericType) { valueType = serializer.GetType().GetGenericArguments()[1]; // TValue } var valueSerializer = BsonSerializer.LookupSerializer(valueType); var valueSerializationOptions = _keyValuePairSerializationOptions.ValueSerializationOptions; if (valueSerializationOptions == null) { var valueDefaultSerializationOptions = valueSerializer.GetDefaultSerializationOptions(); // special case for legacy dictionaries: allow BsonRepresentation on object if (valueDefaultSerializationOptions == null && serializer.GetType() == typeof(DictionarySerializer) && attribute.GetType() == typeof(BsonRepresentationAttribute)) { valueDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute } if (valueDefaultSerializationOptions == null) { var message = string.Format( "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the value serializer is of type {2}.", BsonUtils.GetFriendlyTypeName(attribute.GetType()), BsonUtils.GetFriendlyTypeName(serializer.GetType()), BsonUtils.GetFriendlyTypeName(valueSerializer.GetType())); throw new NotSupportedException(message); } valueSerializationOptions = valueDefaultSerializationOptions.Clone(); } valueSerializationOptions.ApplyAttribute(valueSerializer, attribute); _keyValuePairSerializationOptions = new KeyValuePairSerializationOptions( _keyValuePairSerializationOptions.Representation, _keyValuePairSerializationOptions.KeySerializationOptions, valueSerializationOptions); }
/// <inheritdoc/> public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { if (type == null) { throw new ArgumentNullException("type"); } if (type.IsGenericType && type.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } var serializerAttributes = type.GetCustomAttributes(typeof(BsonSerializerAttribute), false); // don't inherit if (serializerAttributes.Length == 1) { var serializerAttribute = (BsonSerializerAttribute)serializerAttributes[0]; return(serializerAttribute.CreateSerializer(type)); } return(null); }
/// <summary> /// Registers the serializer. /// </summary> /// <param name="type">The type.</param> /// <param name="serializer">The serializer.</param> public void RegisterSerializer(Type type, IBsonSerializer serializer) { if (type == null) { throw new ArgumentNullException("type"); } if (serializer == null) { throw new ArgumentNullException("serializer"); } var typeInfo = type.GetTypeInfo(); if (typeof(BsonValue).IsAssignableFrom(type)) { var message = string.Format("A serializer cannot be registered for type {0} because it is a subclass of BsonValue.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } if (!_cache.TryAdd(type, serializer)) { var message = string.Format("There is already a serializer registered for type {0}.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } }
// private methods private IList CreateInstance(Type type) { string message; if (type.IsInterface) { // in the case of an interface pick a reasonable class that implements that interface if (type == typeof(IEnumerable) || type == typeof(ICollection) || type == typeof(IList)) { return(new ArrayList()); } } else { if (type == typeof(ArrayList)) { return(new ArrayList()); } else if (typeof(IEnumerable).IsAssignableFrom(type)) { var instance = Activator.CreateInstance(type); var list = instance as IList; if (list == null) { message = string.Format("Enumerable class {0} does not implement IList so it can't be deserialized.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); } return(list); } } message = string.Format("EnumerableSerializer can't be used with type {0}.", BsonUtils.GetFriendlyTypeName(type)); throw new BsonSerializationException(message); }
public static void RegisterSerializer(Type type, Type serializerType) { // don't allow a serializer to be registered for subclasses of BsonValue if (typeof(BsonValue).IsAssignableFrom(type)) { throw new PBException("A serializer cannot be registered for type {0} because it is a subclass of BsonValue.", BsonUtils.GetFriendlyTypeName(type)); } if (_trace) { pb.Trace.WriteLine($"PBSerializationProvider_v1 : register type \"{type.zGetTypeName()}\""); } if (__serializers.ContainsKey(type)) { __serializers[type] = serializerType; } else { //__serializers.Add(type, serializer); __serializers.Add(type, serializerType); } }
/// <inheritdoc/> public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry) { if (type == null) { throw new ArgumentNullException("type"); } var typeInfo = type.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } if (typeInfo.IsInterface) { var serializerTypeDefinition = typeof(DiscriminatedInterfaceSerializer <>); return(CreateGenericSerializer(serializerTypeDefinition, new[] { type }, serializerRegistry)); } return(null); }
// public methods /// <summary> /// Gets the serializer for the specified <paramref name="type" />. /// </summary> /// <param name="type">The type.</param> /// <returns> /// The serializer. /// </returns> public IBsonSerializer GetSerializer(Type type) { if (type == null) { throw new ArgumentNullException("type"); } var typeInfo = type.GetTypeInfo(); if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters) { var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type)); throw new ArgumentException(message, "type"); } return(_cache.GetOrAdd(type, CreateSerializer)); }