As the title says. I have a custom serializer for a specific data type. It consists out of a few fields, one of them being an enum. We want to save all enums as string, thus I registered a convention like that:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention(), new EnumRepresentationConvention(BsonType.String) };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
When I try to get the correct serializer with BsonSerializer.LookupSerializer<UnitType>();
all I get is an enum serializer that has the default representation “Int32” set. Why does it not stick to the convention? It would be nice if it would just use the global settings. I can hard-code it by creating the serializer on my own, but that kind of defeats the purpose of global settings in the first place…
Is this a bug?
Thanks!
Hi, @Manuel_Eisenschink,
I understand that you are wondering why EnumRepresentationConvention
isn’t used when looking up an enum serializer. This has to do with how conventions are applied. EnumRepresentationConvention
- like CamelCaseElementNameConvention
- are IMemberMapConvention
conventions which means that they’re applied when mapping a member of a BsonClassMap<T>
, specifically when BsonClassMap<T>.AutoMap()
is called. This might not be obvious as when calling BsonSerializer.LookupSerializer<T>()
and T
is not yet registered, a BsonClassMap<T>
is created, BSON attributes are applied (by another convention), AutoMap()
called, and the serializer registered automatically. Thus in a lot of cases, you are not aware that a BsonClassMap<T>
and BsonClassMapSerializer
have been created on your behalf.
With serializers, you can override the defaults by registering your own serializers during application bootstrapping before any serializers are looked up. For instance:
var enumSerializer = new EnumSerializer<UnitType>(BsonType.String);
BsonSerializer.RegisterSerializer(enumSerializer);
var serializer = BsonSerializer.LookupSerializer<UnitType>() as IRepresentationConfigurable;
Console.WriteLine(serializer.Representation); // outputs String
If you have a known list of enumerations in your application, you could register them during application bootstrapping like this. If you have a lot of enums, this could become tedious. You could write code similar to the following to register all enums in your application assembly or in a namespace:
var enums = typeof(UnitType).Assembly.GetTypes().Where(x => x.IsEnum);
var genericSerializer = typeof(EnumSerializer<>);
foreach (var @enum in enums)
{
var enumSerializerType = genericSerializer.MakeGenericType(@enum);
var enumSerializer = (IBsonSerializer)Activator.CreateInstance(enumSerializerType, BsonType.String);
BsonSerializer.RegisterSerializer(@enum, enumSerializer);
}
Hope this helps.
Sincerely,
James
1 Like