Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow Int32 Overflow in MongoDB C# 2.0 (New Driver)

Tags:

c#

mongodb

I have a uint32 to serialize to MongoDB.

I used to be able to do this using the following code from https://jira.mongodb.org/browse/CSHARP-252

public class AlwaysAllowUInt32OverflowConvention : ISerializationOptionsConvention
{
    public IBsonSerializationOptions GetSerializationOptions(MemberInfo memberInfo)
    {
        Type type = null;
        var fieldInfo = memberInfo as FieldInfo;
        if (fieldInfo != null)
        {
            type = fieldInfo.FieldType;
        }
        var propertyInfo = memberInfo as PropertyInfo;
        if (propertyInfo != null)
        {
            type = propertyInfo.PropertyType;
        }


        if (type == typeof(uint))
        {
            return new RepresentationSerializationOptions(BsonType.Int32) { AllowOverflow = true };
        }
        else
        {
            return null;
        }
    }
}

However in the new MongoDB library the ISerializationOptionsConvention and RepresentationSerializationOptions do not exist. I've had a look and cannot see how to register a default ConventionPack (?) for allowing uint32 to overflow int32 on the new library.

How can I do this without adding a BsonRepresentation attribute to my POCO?

like image 974
James Avatar asked Jan 09 '23 01:01

James


2 Answers

There are two ways I can think of that you can do this. Probably the easiest is to simply register a suitably configured serializer for type UInt32, like this:

var uint32Serializer = new UInt32Serializer(BsonType.Int32, new RepresentationConverter(true, true));
BsonSerializer.RegisterSerializer(uint32Serializer);

If you wanted to do it using conventions (which would only apply when mapping classes automatically), you could do this:

public class AlwaysAllowUInt32OverflowConvention : IMemberMapConvention
{
    public string Name
    {
        get { return "AlwaysAllowUInt32Overflow"; }
    }

    public void Apply(BsonMemberMap memberMap)
    {
        if (memberMap.MemberType == typeof(UInt32))
        {
            var uint32Serializer = new UInt32Serializer(BsonType.Int32, new RepresentationConverter(true, true));
            memberMap.SetSerializer(uint32Serializer);
        }
    }
}

And register the convention like this:

var alwaysAllowUInt32OverflowConvention = new AlwaysAllowUInt32OverflowConvention();
var conventionPack = new ConventionPack();
conventionPack.Add(alwaysAllowUInt32OverflowConvention);
ConventionRegistry.Register("AlwaysAllowUInt32Overflow", conventionPack, t => true);
like image 110
Robert Stam Avatar answered Jan 16 '23 01:01

Robert Stam


You can do it through IBsonSerializer

public class UInt32ToInt64Serializer : IBsonSerializer
{
    public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return (uint)context.Reader.ReadInt64();
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        context.Writer.WriteInt64((uint)value);
    }

    public Type ValueType { get { return typeof (uint); } }
}

and serializer should be registered

BsonSerializer.RegisterSerializer(typeof(uint), new UInt32ToInt64Serializer());
like image 45
rnofenko Avatar answered Jan 16 '23 02:01

rnofenko