Sérialiseur de collection personnalisé MongoDb

J’ai quatre cours simples

public class Zoo{ public ObjectId Id { get; set; } public List Animals { get; set; } } public class Animal{ public ObjectId Id { get; set; } public ssortingng Name { get; set; } } public class Tiger : Animal{ public double Height { get; set; } } public class Zebra : Animal{ public long SsortingpesAmount { get; set; } } 

J’ai créé le sérialiseur personnalisé qui me permet de stocker un object Animal dans une collection distincte (“animaux”).

 class MyAnimalSerializer : SerializerBase { public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, Animal value) { context.Writer.WriteStartDocument(); context.Writer.WriteName("_id"); context.Writer.WriteObjectId(ObjectId.GenerateNewId()); context.Writer.WriteName("_t"); context.Writer.WriteSsortingng(value.GetType().Name); context.Writer.WriteName("Name"); context.Writer.WriteSsortingng(value.Name); switch (value.AnimalType) { case AnimalType.Tiger: context.Writer.WriteName("Height"); context.Writer.WriteDouble((value as Tiger).Height); break; case AnimalType.Zebra: context.Writer.WriteName("SsortingpesAmount"); context.Writer.WriteInt32((value as Zebra).SsortingpesAmount); break; default: break; } context.Writer.WriteEndDocument(); } public override Animal Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args) { context.Reader.ReadStartDocument(); ObjectId id = context.Reader.ReadObjectId(); ssortingng object_type = context.Reader.ReadSsortingng(); ssortingng animal_name = context.Reader.ReadSsortingng(); switch (object_type) { case "Tiger": double tiger_height = context.Reader.ReadDouble(); context.Reader.ReadEndDocument(); return new Tiger() { Id = id, Name = animal_name, Height = tiger_height }; default: long zebra_ssortingpes = context.Reader.ReadInt64(); context.Reader.ReadEndDocument(); return new Zebra() { Id = id, Name = animal_name, SsortingpesAmount = zebra_ssortingpes }; } return null; } } 

Ce qui fonctionne bien et me permet aussi des choses comme ça:

 MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Animal), new MyAnimalSerializer()); IMongoCollection collection = db.GetCollection("animals"); var lst = await collection.Find(new BsonDocument()).ToListAsync(); 

Mais je ne peux pas faire la même chose lorsque les animaux sont stockés dans Zoo et ne peuvent pas désérialiser Zoo de la collection Zoo:

 IMongoCollection collection = db.GetCollection("zoocollection"); var lst = await collection.Find(new BsonDocument()).ToListAsync(); //not working here 

Est-il possible de créer un sérialiseur de collection personnalisé pour le champ?

 public List Animals { get; set; } 

Quelqu’un pourrait-il donner un exemple? Merci d’avance.

Avez-vous visité cette page de document ? Il existe également des exemples de classes polymorphes.

Voici mon exemple de stockage d’objects:

 public class Zoo { [BsonId] public ObjectId Id { get; set; } public List Animals { get; set; } } [BsonDiscriminator(RootClass = true)] [BsonKnownTypes(typeof(Tiger), typeof(Zebra))] public class Animal { [BsonId] public ObjectId Id { get; set; } public ssortingng Name { get; set; } } public class Tiger : Animal { public double Height { get; set; } } public class Zebra : Animal { public long SsortingpesAmount { get; set; } } public class MongoDocumentsDatabase { ///  /// MongoDB Server ///  private readonly MongoClient _client; ///  /// Name of database ///  private readonly ssortingng _databaseName; public MongoUrl MongoUrl { get; private set; } ///  /// Opens connection to MongoDB Server ///  public MongoDocumentsDatabase(Ssortingng connectionSsortingng) { MongoUrl = MongoUrl.Create(connectionSsortingng); _databaseName = MongoUrl.DatabaseName; _client = new MongoClient(connectionSsortingng); } ///  /// Get database ///  public IMongoDatabase Database { get { return _client.GetDatabase(_databaseName); } } public IMongoCollection Zoo { get { return Database.GetCollection("zoo"); } } } class Program { static void Main(ssortingng[] args) { var connectionSsortingng = "mongodb://admin:admin@localhost:27017/testDatabase"; var pr = new Program(); pr.Save(connectionSsortingng); var zoo = pr.Get(connectionSsortingng); foreach (var animal in zoo.Animals) { Console.WriteLine(animal.Name + " " + animal.GetType()); } } public void Save(ssortingng connectionSsortingng) { var zoo = new Zoo { Animals = new List { new Tiger { Height = 1, Name = "Tiger1" }, new Zebra { Name = "Zebra1", SsortingpesAmount = 100 } } }; var database = new MongoDocumentsDatabase(connectionSsortingng); database.Zoo.InsertOneAsync(zoo).Wait(); } public Zoo Get(ssortingng connectionSsortingng) { var database = new MongoDocumentsDatabase(connectionSsortingng); var task = database.Zoo.Find(e => true).SingleAsync(); task.Wait(); return task.Result; } } 

Voici comment les objects ont été stockés dans la firebase database (Robomongo) entrez la description de l'image ici

Et résultat final: entrez la description de l'image ici

Merci beaucoup Anton Putau pour la solution la plus simple possible.

Mais il y en a un autre. Pour sérialiser des objects manuellement:

 public class MyListAnimalSerializer : SerializerBase> { public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, List value) { context.Writer.WriteStartArray(); foreach (Animal mvnt in value) { context.Writer.WriteStartDocument(); switch (mvnt.GetType().Name) { case "Tiger": //your serialization here break; case "Zebra": //your serialization here break; default: break; } context.Writer.WriteEndDocument(); } context.Writer.WriteEndArray(); } public override List Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args) { context.Reader.ReadStartArray(); List result = new List(); while (true) { try { //this catch block only need to identify the end of the Array context.Reader.ReadStartDocument(); } catch (Exception exp) { context.Reader.ReadEndArray(); break; } var type = context.Reader.ReadSsortingng(); var _id = context.Reader.ReadObjectId(); var name = context.Reader.ReadSsortingng(); if (type == "Tiger") { double tiger_height = context.Reader.ReadDouble(); result.Add(new Tiger() { Id = id, Name = animal_name, Height = tiger_height }); } else { long zebra_ssortingpes = context.Reader.ReadInt64(); result.Add(return new Zebra() { Id = id, Name = animal_name, SsortingpesAmount = zebra_ssortingpes }); } context.Reader.ReadEndDocument(); } return result; } } 

Et vous devez simplement annoter le champ IEnumerable pour utiliser votre sérialiseur:

 [BsonSerializer(typeof(MyListAnimalSerializer))] public List Animals { get; set; }