private IBsonSerializer GetCollectionSerializer(Type type)
{
Type implementedGenericDictionaryInterface = null;
Type implementedGenericEnumerableInterface = null;
Type implementedDictionaryInterface = null;
Type implementedEnumerableInterface = null;
var implementedInterfaces = new List<Type>(type.GetInterfaces());
if (type.IsInterface)
{
implementedInterfaces.Add(type);
}
foreach (var implementedInterface in implementedInterfaces)
{
if (implementedInterface.IsGenericType)
{
var genericInterfaceDefinition = implementedInterface.GetGenericTypeDefinition();
if (genericInterfaceDefinition == typeof(IDictionary<,>))
{
implementedGenericDictionaryInterface = implementedInterface;
}
if (genericInterfaceDefinition == typeof(IEnumerable<>))
{
implementedGenericEnumerableInterface = implementedInterface;
}
}
else
{
if (implementedInterface == typeof(IDictionary))
{
implementedDictionaryInterface = implementedInterface;
}
if (implementedInterface == typeof(IEnumerable))
{
implementedEnumerableInterface = implementedInterface;
}
}
}
// the order of the tests is important
if (implementedGenericDictionaryInterface != null)
{
var keyType = implementedGenericDictionaryInterface.GetGenericArguments()[0];
var valueType = implementedGenericDictionaryInterface.GetGenericArguments()[1];
var genericSerializerDefinition = typeof(DictionarySerializer<,>);
var genericSerializerType = genericSerializerDefinition.MakeGenericType(keyType, valueType);
return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
}
else if (implementedDictionaryInterface != null)
{
return new DictionarySerializer();
}
else if (implementedGenericEnumerableInterface != null)
{
var valueType = implementedGenericEnumerableInterface.GetGenericArguments()[0];
var readOnlyCollectionType = typeof(ReadOnlyCollection<>).MakeGenericType(valueType);
Type genericSerializerDefinition;
if (readOnlyCollectionType.IsAssignableFrom(type))
{
genericSerializerDefinition = typeof(ReadOnlyCollectionSerializer<>);
if (type != readOnlyCollectionType)
{
BsonSerializer.RegisterDiscriminator(type, type.Name);
}
}
else
{
genericSerializerDefinition = typeof(EnumerableSerializer<>);
}
var genericSerializerType = genericSerializerDefinition.MakeGenericType(valueType);
return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
}
else if (implementedEnumerableInterface != null)
{
return new EnumerableSerializer();
}
return null;
}
}