Example #1
0
        /// <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);
        }
Example #2
0
        // 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);
        }
Example #6
0
        // 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));
        }
Example #8
0
        /// <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);
                }
            }
        }
Example #9
0
        /*******************************************/

        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);
        }
Example #11
0
        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);
        }
Example #13
0
        /// <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();
            }
        }
Example #17
0
        /// <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;
        }
Example #20
0
        /// <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));
                }
            }
        }
Example #21
0
        // 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));
        }
Example #23
0
        // 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);
        }
Example #24
0
        // 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);
            }
        }
Example #27
0
        // 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);
        }
Example #28
0
        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));
        }