LiteDB icon indicating copy to clipboard operation
LiteDB copied to clipboard

OnSerializing/OnDeserialized methods

Open devmaestro1 opened this issue 3 years ago • 1 comments

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.

devmaestro1 avatar May 06 '22 05:05 devmaestro1

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

devmaestro1 avatar May 09 '22 02:05 devmaestro1