public IBsonSerializer GetSerializer(Type type)
{
Type serializerType;
if (__serializers.TryGetValue(type, out serializerType))
{
return (IBsonSerializer)Activator.CreateInstance(serializerType);
}
// use BsonDocumentSerializer for all subclasses of BsonDocument also
if (typeof(BsonDocument).IsAssignableFrom(type))
{
return BsonDocumentSerializer.Instance;
}
// use BsonIBsonSerializableSerializer for all classes that implement IBsonSerializable
if (typeof(IBsonSerializable).IsAssignableFrom(type))
{
return BsonIBsonSerializableSerializer.Instance;
}
if (type.IsGenericType)
{
var genericTypeDefinition = type.GetGenericTypeDefinition();
Type genericSerializerDefinition;
if (__genericSerializerDefinitions.TryGetValue(genericTypeDefinition, out genericSerializerDefinition))
{
var genericSerializerType = genericSerializerDefinition.MakeGenericType(type.GetGenericArguments());
return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
}
}
if (type.IsArray)
{
var elementType = type.GetElementType();
switch (type.GetArrayRank())
{
case 1:
var arraySerializerDefinition = typeof(ArraySerializer<>);
var arraySerializerType = arraySerializerDefinition.MakeGenericType(elementType);
return (IBsonSerializer)Activator.CreateInstance(arraySerializerType);
case 2:
var twoDimensionalArraySerializerDefinition = typeof(TwoDimensionalArraySerializer<>);
var twoDimensionalArraySerializerType = twoDimensionalArraySerializerDefinition.MakeGenericType(elementType);
return (IBsonSerializer)Activator.CreateInstance(twoDimensionalArraySerializerType);
case 3:
var threeDimensionalArraySerializerDefinition = typeof(ThreeDimensionalArraySerializer<>);
var threeDimensionalArraySerializerType = threeDimensionalArraySerializerDefinition.MakeGenericType(elementType);
return (IBsonSerializer)Activator.CreateInstance(threeDimensionalArraySerializerType);
default:
var message = string.Format("No serializer found for array for rank {0}.", type.GetArrayRank());
throw new BsonSerializationException(message);
}
}
if (type.IsEnum)
{
return new EnumSerializer();
}
// classes that implement IDictionary or IEnumerable are serialized using either DictionarySerializer or EnumerableSerializer
// this does mean that any additional public properties the class might have won't be serialized (just like the XmlSerializer)
var collectionSerializer = GetCollectionSerializer(type);
if (collectionSerializer != null)
{
return collectionSerializer;
}
// we'll try our best by attempting to find a discriminator hoping it points
// us to a concrete type with a serializer.
if (type.IsInterface)
{
return InterfaceSerializer.Instance;
}
return null;
}