/// <summary> /// Initializes a new instance of the DictionarySerializationOptions class. /// </summary> /// <param name="representation">The representation to use for a Dictionary.</param> /// <param name="keyValuePairSerializationOptions">The serialization options for the key/value pairs in the dictionary.</param> public DictionarySerializationOptions(DictionaryRepresentation representation, KeyValuePairSerializationOptions keyValuePairSerializationOptions) { if (keyValuePairSerializationOptions == null) { throw new ArgumentNullException("keyValuePairSerializationOptions"); } _representation = representation; _keyValuePairSerializationOptions = keyValuePairSerializationOptions; }
/// <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)value; var dictionarySerializationOptions = EnsureSerializationOptions(options); var dictionaryRepresentation = dictionarySerializationOptions.Representation; var keyValuePairSerializationOptions = dictionarySerializationOptions.KeyValuePairSerializationOptions; if (dictionaryRepresentation == DictionaryRepresentation.Dynamic) { dictionaryRepresentation = DictionaryRepresentation.Document; foreach (object key in dictionary.Keys) { var name = key as string; // check for null and type string at the same time if (name == null || name[0] == '$' || name.IndexOf('.') != -1) { dictionaryRepresentation = DictionaryRepresentation.ArrayOfArrays; break; } } } switch (dictionaryRepresentation) { case DictionaryRepresentation.Document: bsonWriter.WriteStartDocument(); foreach (DictionaryEntry dictionaryEntry in dictionary) { bsonWriter.WriteName((string)dictionaryEntry.Key); BsonSerializer.Serialize(bsonWriter, typeof(object), dictionaryEntry.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 (DictionaryEntry dictionaryEntry in dictionary) { var keyValuePair = new KeyValuePair<object, object>(dictionaryEntry.Key, dictionaryEntry.Value); _keyValuePairSerializer.Serialize( bsonWriter, typeof(KeyValuePair<object, object>), keyValuePair, keyValuePairSerializationOptions); } bsonWriter.WriteEndArray(); break; default: var message = string.Format("'{0}' is not a valid IDictionary representation.", dictionaryRepresentation); throw new BsonSerializationException(message); } } }
/// <summary> /// Initializes a new instance of the DictionarySerializationOptions class. /// </summary> /// <param name="representation">The representation to use for a Dictionary.</param> public DictionarySerializationOptions(DictionaryRepresentation representation) { _representation = representation; _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone(); }
// constructors /// <summary> /// Initializes a new instance of the DictionarySerializationOptions class. /// </summary> public DictionarySerializationOptions() { _keyValuePairSerializationOptions = (KeyValuePairSerializationOptions)KeyValuePairSerializationOptions.Defaults.Clone(); }
// 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); }