I have a collection in my database where I log events. Each type of event has a different set of data. I've defined this with the following class:
[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; }
}
Now - this works pretty good to some extent. As long as the elements of the EventData
dictionary are simple types...
var event = new LogEvent("JobQueues"){
EventData = new Dictionary<string, object>(){
{ "JobId": "job-123" },
{ "QueueName": "FastLane" }
}
}
_mongoCollection.InsertOne(event);
...I get mongo documents like
{
_id: ObjectId(...),
EventType: "JobQueued",
JobId: "job-123",
QueueName: "FastLane"
}
But as soon as I try to add a custom type to the dictionary, things stops working.
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} }
}
}
This gives me errors like ".NET type ... cannot be mapped to BsonType."
If I remove the [BsonExtraElements]
tag, and [BsonDictionaryOptions(DictionaryRepresentation.Document)]
It will start serialize stuff without errors, but it will give me a complete different document which I don't like..
{
_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"]
}
}
}
What I want, is the following result:
{
_id: ObjectId(...),
EventType: "JobQueued",
JobId: "job-123",
QueueName: "FastLane",
User: {
Name: "username",
Age: 10
},
JobParams : ["param-1", "param-2"]
}
Does anyone know how to achieve that?
(I'm using the C# mongodriver v2.3)
So works MongoDriver, because it needs information of the type to deserilize it back. What you could do, is to write and register your own CustomMapper for User class:
Somewhere on starting program:
That will work, and i have managed to serialize your data exact as you want.
But: As you want to deserialize it back, you wil get your
User
class asDictionary
, because driver will have no information about hiow to deserialize it: