Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB - override default Serializer for a C# primitive type

I'd like to change the representation of C# Doubles to rounded Int64 with a four decimal place shift in the serialization C# Driver's stack for MongoDB. In other words, store (Double)29.99 as (Int64)299900

I'd like this to be transparent to my app. I've had a look at custom serializers but I don't want to override everything and then switch on the Type with fallback to the default, as that's a bit messy.

I can see that RegisterSerializer() won't let me add one for an existing type, and that BsonDefaultSerializationProvider has a static list of primitive serializers and it's marked as internal with private members so I can't easily subclass.

I can also see that it's possible to RepresentAs Int64 for Doubles, but this is a cast not a conversion. I need essentially a cast AND a conversion in both serialization directions.

I wish I could just give the default serializer a custom serializer to override one of it's own, but that would mean a dirty hack.

Am I missing a really easy way?

like image 245
cirrus Avatar asked Aug 30 '12 16:08

cirrus


1 Answers

You can also use your own serialization provider to tell Mongo which serializer to use for certain types, which I ended up doing to mitigate some of the timing issues mentioned when trying to override existing serializers. Here's an example of a serialisation provider that overrides how to serialize decimals:

public class CustomSerializationProvider : IBsonSerializationProvider
{
    public IBsonSerializer GetSerializer(Type type)
    {
        if (type == typeof(decimal)) return new DecimalSerializer(BsonType.Decimal128);

        return null; // falls back to Mongo defaults
    }
}

If you return null from your custom serialization provider, it will fall back to using Mongo's default serialization provider.

Once you've written your provider, you just need to register it:

BsonSerializer.RegisterSerializationProvider(new CustomSerializationProvider());
like image 111
adrian Avatar answered Oct 27 '22 15:10

adrian