简体   繁体   中英

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

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?

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);

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM