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; // key might not be a string
if (string.IsNullOrEmpty(name) || name[0] == '$' || name.IndexOf('.') != -1 || name.IndexOf('\0') != -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);
}
}
}