// 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 itemSerializer = serializer.GetItemSerializationInfo().Serializer;
            if (_itemSerializationOptions == null)
            {
                var itemDefaultSerializationOptions = itemSerializer.GetDefaultSerializationOptions();

                // special case for legacy collections: allow BsonRepresentation on object
                if (itemDefaultSerializationOptions == null &&
                    (serializer.GetType() == typeof(EnumerableSerializer) || serializer.GetType() == typeof(QueueSerializer) || serializer.GetType() == typeof(StackSerializer)) &&
                    attribute.GetType() == typeof(BsonRepresentationAttribute))
                {
                    itemDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute
                }

                if (itemDefaultSerializationOptions == null)
                {
                    var message = string.Format(
                        "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the item serializer is of type {2}.",
                        BsonUtils.GetFriendlyTypeName(attribute.GetType()),
                        BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                        BsonUtils.GetFriendlyTypeName(itemSerializer.GetType()));
                    throw new NotSupportedException(message);
                }

                _itemSerializationOptions = itemDefaultSerializationOptions.Clone();
            }
            _itemSerializationOptions.ApplyAttribute(itemSerializer, attribute);
        }
Beispiel #2
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 itemSerializer = serializer.GetItemSerializationInfo().Serializer;

            if (_itemSerializationOptions == null)
            {
                var itemDefaultSerializationOptions = itemSerializer.GetDefaultSerializationOptions();

                // special case for legacy collections: allow BsonRepresentation on object
                if (itemDefaultSerializationOptions == null &&
                    (serializer.GetType() == typeof(EnumerableSerializer) || serializer.GetType() == typeof(QueueSerializer) || serializer.GetType() == typeof(StackSerializer)) &&
                    attribute.GetType() == typeof(BsonRepresentationAttribute))
                {
                    itemDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute
                }

                if (itemDefaultSerializationOptions == null)
                {
                    var message = string.Format(
                        "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the item serializer is of type {2}.",
                        BsonUtils.GetFriendlyTypeName(attribute.GetType()),
                        BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                        BsonUtils.GetFriendlyTypeName(itemSerializer.GetType()));
                    throw new NotSupportedException(message);
                }

                _itemSerializationOptions = itemDefaultSerializationOptions.Clone();
            }
            _itemSerializationOptions.ApplyAttribute(itemSerializer, attribute);
        }
        // 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 items
            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;
                }
            }

            var itemSerializer = serializer.GetItemSerializationInfo().Serializer;

            if (_itemSerializationOptions == null)
            {
                var itemDefaultSerializationOptions = itemSerializer.GetDefaultSerializationOptions();

                // special case for legacy dictionaries: allow BsonRepresentation on object
                if (itemDefaultSerializationOptions == null &&
                    serializer.GetType() == typeof(DictionarySerializer) &&
                    attribute.GetType() == typeof(BsonRepresentationAttribute))
                {
                    itemDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute
                }

                if (itemDefaultSerializationOptions == null)
                {
                    var message = string.Format(
                        "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the item serializer is of type {2}.",
                        BsonUtils.GetFriendlyTypeName(attribute.GetType()),
                        BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                        BsonUtils.GetFriendlyTypeName(itemSerializer.GetType()));
                    throw new NotSupportedException(message);
                }

                _itemSerializationOptions = itemDefaultSerializationOptions.Clone();
            }

            _itemSerializationOptions.ApplyAttribute(itemSerializer, attribute);
        }
Beispiel #4
0
        /// <summary>
        /// Serialize(s) the object of type <c>T</c>.
        /// </summary>
        /// <param name="value">The instance of <c>T</c> to be serialized.</param>
        /// <param name="isISODateTime">
        /// 1. <c>true</c>, the datetime would serialize as iso datetime format which is consistent with mongodb, like "yyyy-MM-ddTHH:mm:ss.FFFFFFFK";
        /// 2. <c>false</c>, the datetime would serialize as local datetime format, such as: "yyyy/MM/dd HH:mm:ss";
        ///
        /// Note:
        /// 1. the default value is false, which means serialize as local datetime format.
        /// 2. in common uses case, you could ommite this parameter for ui display usage, but in backup & restore scenario,
        /// u must set this parameter as true!! because the mongodb driver only use  the iso datetime format to do serialization,
        /// so for consistence consideration, we must set this parameter to true!!!
        /// </param>
        /// <returns>Th serialized string.</returns>
        public string Serializer(T value, bool isISODateTime)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            using var streamWriter = new StringWriter();
            using (var bsonWriter = new CustomerJsonWriter(streamWriter, this.m_jsonSerializerSettings, isISODateTime))
            {
                IBsonSerializer serializer = BsonSerializer.LookupSerializer(typeof(T));
                if (serializer.ValueType != typeof(T))
                {
                    var message = string.Format("Serializer type {0} value type does not match document types {1}.",
                                                serializer.GetType().FullName,
                                                typeof(T).FullName);
                    throw new ArgumentException(message, "serializer");
                }

                Action <BsonSerializationContext.Builder> configurator = null;
                var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                BsonSerializationArgs args = new BsonSerializationArgs(typeof(T), false, true); //default(BsonSerializationArgs);
                serializer.Serialize(context, args, value);
            }
            streamWriter.Flush();

            return(streamWriter.ToString());
        }
        public static void Resolve(
            string fieldName,
            IBsonSerializer serializer,
            out string?resolvedFieldName,
            out IBsonSerializer?resolvedFieldSerializer)
        {
            BsonSerializationInfo serializationInfo;

            resolvedFieldName       = fieldName;
            resolvedFieldSerializer = null;

            var documentSerializer = serializer as IBsonDocumentSerializer;

            if (serializer is IBsonArraySerializer bsonArraySerializer &&
                bsonArraySerializer.TryGetItemSerializationInfo(out serializationInfo))
            {
                resolvedFieldSerializer = serializationInfo.Serializer;
                documentSerializer      = serializationInfo.Serializer as IBsonDocumentSerializer;
            }

            if (documentSerializer == null)
            {
                return;
            }

            // shortcut BsonDocumentSerializer since it is so common
            if (serializer.GetType() == typeof(BsonDocumentSerializer))
            {
                return;
            }

            // first, lets try the quick and easy one, which will be a majority of cases
            if (documentSerializer.TryGetMemberSerializationInfo(fieldName, out serializationInfo))
            {
                resolvedFieldName       = serializationInfo.ElementName;
                resolvedFieldSerializer = serializationInfo.Serializer;
                return;
            }

            // now lets go and do the more difficult variant
            string[] nameParts = fieldName.Split('.');
            if (nameParts.Length <= 1)
            {
                // if we only have 1, then it's no different than what we did above
                // when we found nothing.
                return;
            }

            IBsonArraySerializer?arraySerializer;

            resolvedFieldSerializer = documentSerializer;
            for (int i = 0; i < nameParts.Length; i++)
            {
                if (nameParts[i] == "$" || nameParts[i].All(char.IsDigit))
                {
                    arraySerializer = resolvedFieldSerializer as IBsonArraySerializer;
                    if (resolvedFieldSerializer is IBsonArraySerializer &&
                        arraySerializer is {} &&
Beispiel #6
0
 public static IBsonSerializer GetItemSerializer(IBsonSerializer serializer)
 {
     if (serializer is IBsonArraySerializer arraySerializer)
     {
         if (arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo))
         {
             return(itemSerializationInfo.Serializer);
         }
         else
         {
             throw new InvalidOperationException($"{serializer.GetType().FullName}.TryGetItemSerializationInfo returned false.");
         }
     }
     else
     {
         throw new InvalidOperationException($"{serializer.GetType().FullName} must implement IBsonArraySerializer to be used with LINQ.");
     }
 }
Beispiel #7
0
        private void RegisterBsonSerializer <T>(IBsonSerializer <T> serializer)
        {
            string typeName = typeof(T).ToString();

            if (_registeredSerializers.TryGetValue(typeName, out Type registeredType))
            {
                if (registeredType != serializer.GetType())
                {
                    throw new BsonSerializationException(
                              $"There is already another " +
                              $"serializer registered for type {typeName}. " +
                              $"Registered serializer is {registeredType.Name}. " +
                              $"New serializer is {serializer.GetType().Name}");
                }

                return;
            }

            BsonSerializer.RegisterSerializer(serializer);

            _registeredSerializers.Add(typeof(T).ToString(), serializer.GetType());
        }
        // protected methods
        /// <summary>
        /// Reconfigures the specified serializer by applying this attribute to it.
        /// </summary>
        /// <param name="serializer">The serializer.</param>
        /// <returns>A reconfigured serializer.</returns>
        /// <exception cref="System.NotSupportedException"></exception>
        protected virtual IBsonSerializer Apply(IBsonSerializer serializer)
        {
            // if none of the overrides applied the attribute to the serializer see if it can be applied to a child serializer
            var childSerializerConfigurable = serializer as IChildSerializerConfigurable;
            if (childSerializerConfigurable != null)
            {
                var childSerializer = childSerializerConfigurable.ChildSerializer;
                var reconfiguredChildSerializer = Apply(childSerializer);
                return childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer);
            }

            var message = string.Format(
                "A serializer of type '{0}' is not configurable using an attribute of type '{1}'.",
                BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                BsonUtils.GetFriendlyTypeName(this.GetType()));
            throw new NotSupportedException(message);
        }
Beispiel #9
0
        // protected methods
        /// <summary>
        /// Reconfigures the specified serializer by applying this attribute to it.
        /// </summary>
        /// <param name="serializer">The serializer.</param>
        /// <returns>A reconfigured serializer.</returns>
        /// <exception cref="System.NotSupportedException"></exception>
        protected virtual IBsonSerializer Apply(IBsonSerializer serializer)
        {
            // if none of the overrides applied the attribute to the serializer see if it can be applied to a child serializer
            var childSerializerConfigurable = serializer as IChildSerializerConfigurable;

            if (childSerializerConfigurable != null)
            {
                var childSerializer             = childSerializerConfigurable.ChildSerializer;
                var reconfiguredChildSerializer = Apply(childSerializer);
                return(childSerializerConfigurable.WithChildSerializer(reconfiguredChildSerializer));
            }

            var message = string.Format(
                "A serializer of type '{0}' is not configurable using an attribute of type '{1}'.",
                BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                BsonUtils.GetFriendlyTypeName(this.GetType()));

            throw new NotSupportedException(message);
        }
Beispiel #10
0
 /// <summary>Returns true if a name based convention is supported.</summary>
 private static bool TypeIsSupported(IBsonSerializer converter)
 => (bool)converter
 .GetType()
 .GetProperty(nameof(QowaivBsonConverter <object> .TypeIsSupported), NonPublicInstance)
 .GetValue(converter, Array.Empty <object>());
        // 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);
        }
Beispiel #12
0
        private static IBsonSerializer GetDictionaryValueSerializer(IBsonSerializer serializer)
        {
            if (serializer is IBsonDictionarySerializer dictionarySerializer)
            {
                return(dictionarySerializer.ValueSerializer);
            }

            throw new InvalidOperationException($"Unable to determine value serializer for dictionary serializer: {serializer.GetType().FullName}.");
        }
        /***************************************************/

        private object DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            // First try to recover the object type
            IBsonReader        reader   = context.Reader;
            BsonReaderBookmark bookmark = reader.GetBookmark();
            Type actualType             = typeof(CustomObject);

            try
            {
                actualType = _discriminatorConvention.GetActualType(reader, typeof(object));
            }
            catch (Exception e)
            {
                BsonDocument doc = null;

                try
                {
                    context.Reader.ReturnToBookmark(bookmark);
                    IBsonSerializer bSerializer = BsonSerializer.LookupSerializer(typeof(BsonDocument));
                    doc = bSerializer.Deserialize(context, args) as BsonDocument;
                }
                catch { }

                if (doc != null && doc.Contains("_t") && doc["_t"].AsString == "DBNull")
                {
                    return(null);
                }
                else
                {
                    actualType = typeof(IDeprecated);
                }
            }
            context.Reader.ReturnToBookmark(bookmark);

            if (actualType == null)
            {
                return(null);
            }

            // Make sure the type is not deprecated
            if (Config.AllowUpgradeFromBson && actualType.IIsDeprecated() && !Config.TypesWithoutUpgrade.Contains(actualType))
            {
                actualType = typeof(IDeprecated);
            }

            // Handle the special case where the type is object
            if (actualType == typeof(object))
            {
                BsonType currentBsonType = reader.GetCurrentBsonType();
                if (currentBsonType == BsonType.Document && context.DynamicDocumentSerializer != null)
                {
                    return(context.DynamicDocumentSerializer.Deserialize(context, args));
                }
                reader.ReadStartDocument();
                reader.ReadEndDocument();
                return(new object());
            }

            // Handle the general case of finding the correct deserialiser and calling it
            try
            {
                IBsonSerializer bsonSerializer = BsonSerializer.LookupSerializer(actualType);

                if (bsonSerializer.GetType().Name == "EnumerableInterfaceImplementerSerializer`2" && context.Reader.CurrentBsonType == BsonType.Document)
                {
                    if (!m_FallbackSerialisers.ContainsKey(actualType))
                    {
                        CreateFallbackSerialiser(actualType);
                    }
                    bsonSerializer = m_FallbackSerialisers[actualType];
                }

                return(bsonSerializer.Deserialize(context, args));
            }
            catch (Exception e)
            {
                context.Reader.ReturnToBookmark(bookmark);

                if (e is FormatException && e.InnerException != null && (e.InnerException is FormatException || e.InnerException is BsonSerializationException))
                {
                    // A child of the object is causing problems. Try to recover from custom object
                    IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject));
                    object          result           = customSerializer.Deserialize(context, args);
                    Guid            objectId         = ((CustomObject)result).BHoM_Guid;

                    if (!Config.TypesWithoutUpgrade.Contains(actualType))
                    {
                        if (m_StackCounter.ContainsKey(objectId))
                        {
                            m_StackCounter[objectId] += 1;
                        }
                        else
                        {
                            m_StackCounter[objectId] = 1;
                        }

                        if (m_StackCounter[objectId] < 10)
                        {
                            result = Convert.FromBson(result.ToBson());
                            m_StackCounter.Remove(objectId);
                        }
                    }

                    if (result is CustomObject)
                    {
                        Engine.Reflection.Compute.RecordWarning("The type " + actualType.FullName + " is unknown -> data returned as custom objects.");
                        Config.TypesWithoutUpgrade.Add(actualType);
                    }

                    return(result);
                }
                else if (actualType != typeof(IDeprecated))
                {
                    // Try the deprecated object serialiser
                    IBsonSerializer deprecatedSerializer = BsonSerializer.LookupSerializer(typeof(IDeprecated));
                    return(deprecatedSerializer.Deserialize(context, args));
                }
                else
                {
                    // Last resort: just return the custom object
                    Engine.Reflection.Compute.RecordWarning("The type " + actualType.FullName + " is unknown -> data returned as custom objects.");
                    IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject));
                    return(customSerializer.Deserialize(context, args));
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Serializes an object to a JSON string.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="nominalType">The nominal type of the objectt.</param>
        /// <param name="writerSettings">The JsonWriter settings.</param>
        /// <param name="serializer">The serializer.</param>
        /// <param name="configurator">The serialization context configurator.</param>
        /// <param name="args">The serialization args.</param>
        /// <returns>
        /// A JSON string.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">nominalType</exception>
        /// <exception cref="System.ArgumentException">serializer</exception>
        public static string ToMyJson(
            this object obj,
            Type nominalType,
            JsonWriterSettings writerSettings = null,
            IBsonSerializer serializer        = null,
            Action <BsonSerializationContext.Builder> configurator = null,
            BsonSerializationArgs args = default(BsonSerializationArgs))
        {
            if (nominalType == null)
            {
                throw new ArgumentNullException("nominalType");
            }

            if (serializer == null)
            {
                serializer = BsonSerializer.LookupSerializer(nominalType);
            }
            if (serializer.ValueType != nominalType)
            {
                var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                throw new ArgumentException(message, "serializer");
            }

            using (var stringWriter = new StringWriter())
            {
                using (var bsonWriter = new CustomJsonWriter(stringWriter, writerSettings ?? JsonWriterSettings.Defaults))
                {
                    var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                    args.NominalType = nominalType;
                    serializer.Serialize(context, args, obj);
                }
                return(stringWriter.ToString());
            }
        }
Beispiel #15
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);
        }
Beispiel #16
0
        public static void Resolve <TDocument>(string fieldName, IBsonSerializer <TDocument> serializer, out string resolvedFieldName, out IBsonSerializer resolvedFieldSerializer)
        {
            resolvedFieldName       = fieldName;
            resolvedFieldSerializer = null;
            var documentSerializer = serializer as IBsonDocumentSerializer;

            if (documentSerializer == null)
            {
                return;
            }

            // shortcut BsonDocumentSerializer since it is so common
            if (serializer.GetType() == typeof(BsonDocumentSerializer))
            {
                return;
            }

            BsonSerializationInfo serializationInfo;

            // first, lets try the quick and easy one, which will be a majority of cases
            if (documentSerializer.TryGetMemberSerializationInfo(fieldName, out serializationInfo))
            {
                resolvedFieldName       = serializationInfo.ElementName;
                resolvedFieldSerializer = serializationInfo.Serializer;
                return;
            }

            // now lets go and do the more difficult variant
            var nameParts = fieldName.Split('.');

            if (nameParts.Length <= 1)
            {
                // if we only have 1, then it's no different than what we did above
                // when we found nothing.
                return;
            }

            IBsonArraySerializer arraySerializer;

            resolvedFieldSerializer = documentSerializer;
            for (int i = 0; i < nameParts.Length; i++)
            {
                if (nameParts[i] == "$" || nameParts[i].All(char.IsDigit))
                {
                    arraySerializer = resolvedFieldSerializer as IBsonArraySerializer;
                    if (arraySerializer != null && arraySerializer.TryGetItemSerializationInfo(out serializationInfo))
                    {
                        resolvedFieldSerializer = serializationInfo.Serializer;
                        continue;
                    }

                    resolvedFieldSerializer = null;
                    break;
                }

                documentSerializer = resolvedFieldSerializer as IBsonDocumentSerializer;
                if (documentSerializer == null || !documentSerializer.TryGetMemberSerializationInfo(nameParts[i], out serializationInfo))
                {
                    // need to check if this is an any element array match
                    arraySerializer = resolvedFieldSerializer as IBsonArraySerializer;
                    if (arraySerializer != null && arraySerializer.TryGetItemSerializationInfo(out serializationInfo))
                    {
                        documentSerializer = serializationInfo.Serializer as IBsonDocumentSerializer;
                        if (documentSerializer == null || !documentSerializer.TryGetMemberSerializationInfo(nameParts[i], out serializationInfo))
                        {
                            resolvedFieldSerializer = null;
                            break;
                        }
                    }
                    else
                    {
                        resolvedFieldSerializer = null;
                        break;
                    }
                }

                nameParts[i]            = serializationInfo.ElementName;
                resolvedFieldSerializer = serializationInfo.Serializer;
            }

            resolvedFieldName = string.Join(".", nameParts);
        }
        // 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 items
            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;
                }
            }

            var itemSerializer = serializer.GetItemSerializationInfo().Serializer;
            if (_itemSerializationOptions == null)
            {
                var itemDefaultSerializationOptions = itemSerializer.GetDefaultSerializationOptions();

                // special case for legacy dictionaries: allow BsonRepresentation on object
                if (itemDefaultSerializationOptions == null && 
                    serializer.GetType() == typeof(DictionarySerializer) && 
                    attribute.GetType() == typeof(BsonRepresentationAttribute))
                {
                    itemDefaultSerializationOptions = new RepresentationSerializationOptions(BsonType.Null); // will be modified later by ApplyAttribute
                }

                if (itemDefaultSerializationOptions == null)
                {
                    var message = string.Format(
                        "A serialization options attribute of type {0} cannot be used when the serializer is of type {1} and the item serializer is of type {2}.",
                        BsonUtils.GetFriendlyTypeName(attribute.GetType()),
                        BsonUtils.GetFriendlyTypeName(serializer.GetType()),
                        BsonUtils.GetFriendlyTypeName(itemSerializer.GetType()));
                    throw new NotSupportedException(message);
                }

                _itemSerializationOptions = itemDefaultSerializationOptions.Clone();
            }

            _itemSerializationOptions.ApplyAttribute(itemSerializer, attribute);
        }
Beispiel #18
0
        /// <summary>
        /// Serializes an object to a BsonDocument.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="nominalType">The nominal type of the object.</param>
        /// <param name="serializer">The serializer.</param>
        /// <param name="configurator">The serialization context configurator.</param>
        /// <param name="args">The serialization args.</param>
        /// <returns>A BsonDocument.</returns>
        /// <exception cref="System.ArgumentNullException">nominalType</exception>
        /// <exception cref="System.ArgumentException">serializer</exception>
        public static BsonDocument ToBsonDocument(
            this object obj,
            Type nominalType,
            IBsonSerializer serializer = null,
            Action <BsonSerializationContext.Builder> configurator = null,
            BsonSerializationArgs args = default(BsonSerializationArgs))
        {
            if (nominalType == null)
            {
                throw new ArgumentNullException("nominalType");
            }

            if (obj == null)
            {
                return(null);
            }

            if (serializer == null)
            {
                var bsonDocument = obj as BsonDocument;
                if (bsonDocument != null)
                {
                    return(bsonDocument); // it's already a BsonDocument
                }

                var convertibleToBsonDocument = obj as IConvertibleToBsonDocument;
                if (convertibleToBsonDocument != null)
                {
                    return(convertibleToBsonDocument.ToBsonDocument()); // use the provided ToBsonDocument method
                }

                serializer = BsonSerializer.LookupSerializer(nominalType);
            }
            if (serializer.ValueType != nominalType)
            {
                var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                throw new ArgumentException(message, "serializer");
            }

            // otherwise serialize into a new BsonDocument
            var document = new BsonDocument();

            using (var bsonWriter = new BsonDocumentWriter(document))
            {
                var context = BsonSerializationContext.CreateRoot(bsonWriter, configurator);
                args.NominalType = nominalType;
                serializer.Serialize(context, args, obj);
            }
            return(document);
        }
Beispiel #19
0
        /// <summary>
        /// Serializes an object to a BSON byte array.
        /// </summary>
        /// <param name="obj">The object.</param>
        /// <param name="nominalType">The nominal type of the object..</param>
        /// <param name="writerSettings">The writer settings.</param>
        /// <param name="serializer">The serializer.</param>
        /// <param name="configurator">The serialization context configurator.</param>
        /// <returns>A BSON byte array.</returns>
        /// <exception cref="System.ArgumentNullException">nominalType</exception>
        /// <exception cref="System.ArgumentException">serializer</exception>
        public static byte[] ToBson(
            this object obj,
            Type nominalType,
            BsonBinaryWriterSettings writerSettings = null,
            IBsonSerializer serializer = null,
            Action <BsonSerializationContext.Builder> configurator = null)
        {
            if (nominalType == null)
            {
                throw new ArgumentNullException("nominalType");
            }

            if (serializer == null)
            {
                serializer = BsonSerializer.LookupSerializer(nominalType);
            }
            if (serializer.ValueType != nominalType)
            {
                var message = string.Format("Serializer type {0} value type does not match document types {1}.", serializer.GetType().FullName, nominalType.FullName);
                throw new ArgumentException(message, "serializer");
            }

            using (var memoryStream = new MemoryStream())
            {
                using (var bsonWriter = new BsonBinaryWriter(memoryStream, writerSettings ?? BsonBinaryWriterSettings.Defaults))
                {
                    var context = BsonSerializationContext.CreateRoot(bsonWriter, nominalType, configurator);
                    serializer.Serialize(context, obj);
                }
                return(memoryStream.ToArray());
            }
        }
Beispiel #20
0
        /***************************************************/

        private object DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            // First try to recover the object type
            IBsonReader        reader   = context.Reader;
            BsonReaderBookmark bookmark = reader.GetBookmark();
            Type actualType             = typeof(CustomObject);

            try
            {
                actualType = _discriminatorConvention.GetActualType(reader, typeof(object));
            }
            catch
            {
                try
                {
                    context.Reader.ReturnToBookmark(bookmark);
                    DeprecatedSerializer deprecatedSerialiser = new DeprecatedSerializer();
                    return(deprecatedSerialiser.Deserialize(context, args));
                }
                catch { }
            }
            context.Reader.ReturnToBookmark(bookmark);

            if (actualType == null)
            {
                return(null);
            }

            // Handle the special case where the type is object
            if (actualType == typeof(object))
            {
                BsonType currentBsonType = reader.GetCurrentBsonType();
                if (currentBsonType == BsonType.Document && context.DynamicDocumentSerializer != null)
                {
                    return(context.DynamicDocumentSerializer.Deserialize(context, args));
                }
                reader.ReadStartDocument();
                reader.ReadEndDocument();
                return(new object());
            }

            // Handle the general case of finding the correct deserialiser and calling it
            try
            {
                if (!BsonClassMap.IsClassMapRegistered(actualType))
                {
                    Compute.RegisterClassMap(actualType); // LookupSerializer creates the classMap if it doesn't exist so important to do it through our own method
                }
                IBsonSerializer bsonSerializer = BsonSerializer.LookupSerializer(actualType);

                if (bsonSerializer.GetType().Name == "EnumerableInterfaceImplementerSerializer`2" && context.Reader.CurrentBsonType == BsonType.Document)
                {
                    if (!m_FallbackSerialisers.ContainsKey(actualType))
                    {
                        CreateFallbackSerialiser(actualType);
                    }
                    bsonSerializer = m_FallbackSerialisers[actualType];
                }
                else if (actualType.Name == "Dictionary`2" && context.Reader.CurrentBsonType == BsonType.Document)
                {
                    DictionarySerializer dicSerialiser = new DictionarySerializer();
                    return(dicSerialiser.Deserialize(context, args));
                }

                return(bsonSerializer.Deserialize(context, args));
            }
            catch (Exception e)
            {
                if (e.Message.Contains("Could not load file or assembly"))
                {
                    Engine.Reflection.Compute.RecordError(e.Message);
                }

                context.Reader.ReturnToBookmark(bookmark);
                DeprecatedSerializer deprecatedSerialiser = new DeprecatedSerializer();
                return(deprecatedSerialiser.Deserialize(context, args));
            }
        }
Beispiel #21
0
 public static object FromJson(
     string json,
     Type nominalType,
     JsonReaderSettings readerSettings = null,
     IBsonSerializer serializer        = null,
     Action <BsonDeserializationContext.Builder> configurator = null)
 {
     if (nominalType == null || json == null)
     {
         throw new ArgumentNullException();
     }
     serializer = serializer ?? BsonSerializer.LookupSerializer(nominalType);
     if (serializer.ValueType != nominalType)
     {
         throw new ArgumentException(string.Format("serializer.ValueType {0} != nominalType {1}.", serializer.GetType().FullName, nominalType.FullName), "serializer");
     }
     using (var textReader = new StringReader(json))
         using (var reader = new JsonReader(textReader, readerSettings ?? JsonReaderSettings.Defaults))
         {
             var context = BsonDeserializationContext.CreateRoot(reader, configurator);
             return(serializer.Deserialize(context));
         }
 }