The mongo driver offers a rich and complete infrastructure to create rich domain entities out of the box. The bson serializer integrated with the mongo driver can tackle all types of entities, it can deserialize entities with private setters and constructors, allowing us to define our entity methods and limit property access.
Cloning an entity may represent one of the first steps in our process, and mongo driver makes it to easy.
Let’s assume the following entity
public class Entity where T : Entity { public T Clone() { //To de defined } }
From this entity we derive two classes, both will have a constructor that is not parameterless (the parameter names i defined in the constructor are different then the name of the properties on purpose, to illustrate the deserializing capabilities)
public class Card : Entity { public int Value { get; private set; } public Card(int v) { this.Value = v; } } public class Deck : Entity { public List Cards { get; private set; } private Deck(Card[] c) { Cards = c.ToList() ?? new List(); } internal static Deck Create(params Card[] cards) { return new Deck(cards); } }
Note that the properties have private setters, Visual studio recommends to remove these setters as they are instantiated in the constructor, but the deserializing process needs these setters to be defined. Classically you may choose to perform this cloning using Newtonsoft, deserialize a serialized instance. But how would this work, since we have these constructors in place:
As you can see, the deserializing process is not correct, we need to make a special serializer class for newtonsoft that would handle this class, but why bother since we are already making everything to work with mongo, why not simply leveraging the mongo driver bson capabilities? Let’s change the entity class to use the BsonSerializer class and see the results
public class Entity where T : Entity { public T Clone() { byte[] serialized = null; using (var stream = new MemoryStream()) { using (BsonBinaryWriter bsonBinaryWriter = new BsonBinaryWriter(stream)) { BsonSerializer.Serialize(bsonBinaryWriter, typeof(T), this); stream.Seek(0, SeekOrigin.Begin); stream.Position = 0; serialized = stream.ToArray(); } } return BsonSerializer.Deserialize(serialized); } }