Tengo una colección en mi base de datos donde registro eventos. Cada tipo de evento tiene un conjunto diferente de datos. He definido esto con la siguiente clase:
[CollectionName("LogEvent")] public class LogEvent { public LogEvent(string eventType) { EventType = eventType; EventData = new Dictionary<string, object>(); } public string EventType { get; private set; } [BsonExtraElements] public IDictionary<string, object> EventData { get; private set; } } Ahora, esto funciona bastante bien hasta cierto punto. Siempre que los elementos del diccionario EventData sean tipos simples...
var event = new LogEvent("JobQueues"){ EventData = new Dictionary<string, object>(){ { "JobId": "job-123" }, { "QueueName": "FastLane" } } } _mongoCollection.InsertOne(event);... Obtengo documentos mongo como
{ _id: ObjectId(...), EventType: "JobQueued", JobId: "job-123", QueueName: "FastLane" }Pero tan pronto como intento agregar un tipo personalizado al diccionario, las cosas dejan de funcionar.
var event = new LogEvent("JobQueues"){ EventData = new Dictionary<string, object>(){ { "JobId": "job-123" }, { "QueueName": "FastLane" }, { "JobParams" : new[]{"param-1", "param-2"}}, { "User" : new User(){ Name = "username", Age = 10} } } } Esto me da errores como ".NET type ... cannot be mapped to BsonType."
Si elimino la etiqueta [BsonExtraElements] y [BsonDictionaryOptions(DictionaryRepresentation.Document)] , comenzará a serializar cosas sin errores, pero me dará un documento completamente diferente que no me gusta.
{ _id: ObjectId(...), EventType: "JobQueued", EventData: { JobId: "job-123", QueueName: "FastLane", User: { _t: "User", Name: "username", Age: 10 }, JobParams : { _t: "System.String[]", _v: ["param-1", "param-2"] } } }Lo que quiero, es el siguiente resultado:
{ _id: ObjectId(...), EventType: "JobQueued", JobId: "job-123", QueueName: "FastLane", User: { Name: "username", Age: 10 }, JobParams : ["param-1", "param-2"] }¿Alguien sabe cómo lograr eso?
(Estoy usando C# mongodriver v2.3)
Así funciona MongoDriver, porque necesita información del tipo para deserilizarlo. Lo que podría hacer es escribir y registrar su propio CustomMapper para la clase de usuario:
public class CustomUserMapper : ICustomBsonTypeMapper { public bool TryMapToBsonValue(object value, out BsonValue bsonValue) { bsonValue = ((User)value).ToBsonDocument(); return true; } }En algún lugar del programa de inicio:
BsonTypeMapper.RegisterCustomTypeMapper(typeof(User), new CustomUserMapper());Eso funcionará, y he logrado serializar sus datos exactamente como lo desea.
Pero: como desea volver a deserializarlo, obtendrá su clase de User como Dictionary , porque el controlador no tendrá información sobre cómo deserializarlo: