OnSerializing/OnDeserialized methods
Hello,
According to #1599, it's possible to do OnSerializing/OnDeserialized methods by using the RegisterType method. The code example below is given:
mapper.RegisterType<MyClass>
(
serialize: o =>
{
var doc = new BsonDocument();
doc["_id"] = o.Id;
doc["Field1"] = o.Field1;
//whatever you want to do
return doc;
},
deserialize: doc =>
{
var o = new MyClass();
o.Id = doc["_id"];
o.Field1 = doc["Field1"];
//whatever you want to do
return o;
}
);
My question is, if I wanted to merely call a OnSerializing or OnDeserialize method but still use the "native" serialization function, how would I do this?
mapper.RegisterType<MyClass>
(
serialize: o =>
{
o.OnSerializing();
var doc = new BsonDocument();
// How to serialize the object as per usual without writing code for each property?
return doc;
},
deserialize: doc =>
{
var o = new MyClass();
// How to deserialize the object as per usual without writing code for each property?
o.OnDeserialize();
return o;
}
);
Appreciate any help.
Thanks.
Here is my current solution to the problem. I have added the methods shown below and they perform a "custom" serialization of the object. If anyone has any improvements, they would be welcome. In particular, I am not sure if this code is optimized for performance since it calls "GetTypeMembers" repeatedly. From what I could see in the LiteDb code, I cannot access the cache of previous calls to this function because it stored as a dictionary of "EntityMapper" and marked as private, Have I missed something?
BsonDocument SerializeObject(object o)
{
var doc = new BsonDocument();
doc["_type"] = new BsonValue(o.GetType().AssemblyQualifiedName);
var members = GetTypeMembers(o.GetType());
foreach (var member in members)
{
var propertInfo = o.GetType().GetProperty(member.Name);
if (propertInfo != null)
{
if (!propertInfo.CanWrite) continue;
// Get the value of the property
var value = propertInfo.GetValue(o, null);
doc[member.Name] = Serialize(value);
}
}
return doc;
}
object DeserializeObject(BsonDocument doc)
{
object o = null;
if (doc.TryGetValue("_type", out var typeField) && typeField.IsString)
{
string assemblyQualifiedName = doc["_type"].AsString;
var instanceType = Type.GetType(assemblyQualifiedName);
o = Activator.CreateInstance(instanceType, true);
foreach (var member in GetTypeMembers(instanceType))
{
BsonValue bsonValue = null;
if (doc.TryGetValue(member.Name, out bsonValue))
{
var value = Deserialize(member.DeclaringType, bsonValue);
o.GetType().GetProperty(member.Name).SetValue(o, value, null);
}
}
}
return o;
}
So now it is possible to register a new class to do this:
RegisterType<MyClass>
(
serialize: o =>
{
o.OnSerializing();
var doc = SerializeObject(o);
return doc;
},
deserialize: doc =>
{
var obj = (MyClass)DeserializeObject((BsonDocument)doc);
obj->OnDeserialized();
return obj;
}
);