Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BsonClassMapSerializer already registered for AbstractClassSerializer

I'm using the Mongo c# driver 2.0 and am running into BsonSerializer registration issues when registering AbstractClassSerializers for my Id value objects.

MongoDB.Bson.BsonSerializationException: There is already a serializer registered for type HistoricalEventId.

When I peek into the BsonSerializer I'm seeing that a BsonClassMapSerializer is already registered for my type.

enter image description here

I'm assuming that a BsonClassMapSerializer is being created for my entity types and it's also creating a BsonClassMapSerializer for the Id field as well. Has anyone run into this before? The Bson serializer code is shown below if that helps.

Sorry if the formatting is wrong, c# doesn't seem to be showing up well.

HistoricalEventIdBsonSerializer

public class HistoricalEventIdBsonSerializer : ToObjectIdBsonSerializer<HistoricalEventId>
{
    public override HistoricalEventId CreateObjectFromObjectId(ObjectId serializedObj)
    {
        HistoricalEventId parsedObj;
        HistoricalEventId.TryParse(serializedObj, out parsedObj);
        return parsedObj;
    }
}

ToObjectIdBsonSerializer

public abstract class ToObjectIdBsonSerializer<T> : AbstractClassSerializer<T> where T : class
{
    private static readonly Type _convertibleType = typeof(IConvertible<ObjectId>);
    public abstract T CreateObjectFromObjectId(ObjectId serializedObj);

    public override T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonType = context.Reader.GetCurrentBsonType();
        ObjectId value;
        switch (bsonType)
        {
            case BsonType.Undefined:
                value = ObjectId.Empty;
                context.Reader.ReadUndefined();
                break;
            case BsonType.Null:
                value = ObjectId.Empty;
                context.Reader.ReadNull();
                break;
            case BsonType.ObjectId:
                value = context.Reader.ReadObjectId();
                break;
            case BsonType.String:
                value = new ObjectId(context.Reader.ReadString());
                break;
            default:
                throw new NotSupportedException("Unable to create the type " + 
                    args.NominalType.Name + " from the bson type " + bsonType + ".");
        }
        return this.CreateObjectFromObjectId(value);
    }

    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value)
    {
        if (value == null)
        {
            context.Writer.WriteObjectId(ObjectId.Empty);
        }
        else
        {
            if (!_convertibleType.IsAssignableFrom(args.NominalType))
            {
                throw new NotSupportedException("The type " + args.NominalType.Name + 
                    " must implement the " + _convertibleType.Name + " interface.");
            }
            var typedObj = (IConvertible<ObjectId>)value;
            context.Writer.WriteObjectId(typedObj.ToValueType());
        }
    }

}

IConvertible

public interface IConvertible<out T>
{
    T ToValueType();
}
like image 400
Nicholas J. Markkula Avatar asked Aug 08 '26 16:08

Nicholas J. Markkula


1 Answers

My assumption must have been correct because I just fixed this by doing the BsonSerializer registration before creating the MongoClient and getting the database. Hopefully this will help someone else.

like image 153
Nicholas J. Markkula Avatar answered Aug 10 '26 11:08

Nicholas J. Markkula