C# MongoDb自定义集合序列化程序

C# MongoDb自定义集合序列化程序,c#,mongodb,serialization,C#,Mongodb,Serialization,我有四节简单的课 public class Zoo{ public ObjectId Id { get; set; } public List<Animal> Animals { get; set; } } public class Animal{ public ObjectId Id { get; set; } public string Name { get; set; } } public class Tiger : Animal{

我有四节简单的课

public class Zoo{
    public ObjectId Id { get; set; } 
    public List<Animal> Animals { get; set; }
}
public class Animal{
    public ObjectId Id { get; set; } 
    public string Name { get; set; } 
}
public class Tiger : Animal{
    public double Height { get; set; }
}
public class Zebra : Animal{
    public long StripesAmount { get; set; }
}
公共类动物园{
公共对象Id{get;set;}
公共列表动物{get;set;}
}
公营动物{
公共对象Id{get;set;}
公共字符串名称{get;set;}
}
公营老虎:动物{
公共双倍高度{get;set;}
}
公共级斑马:动物{
公共长条带装入{get;set;}
}
我已经创建了自定义序列化程序,它允许我将动物对象存储在不同的集合(“动物”)中

class MyAnimalSerializer:SerializerBase
{
public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext,MongoDB.Bson.Serialization.BsonSerializationArgs args,动物值)
{
context.Writer.WriteStartDocument();
context.Writer.WriteName(“\u id”);
context.Writer.WriteObjectId(ObjectId.generateWid());
context.Writer.WriteName(“\t”);
context.Writer.WriteString(value.GetType().Name);
context.Writer.WriteName(“名称”);
context.Writer.WriteString(value.Name);
开关(value.AnimalType)
{
案例动物类型。老虎:
context.Writer.WriteName(“高度”);
context.Writer.WriteDouble((值为Tiger.Height);
打破
案例动物类型。斑马:
context.Writer.WriteName(“StripesAmount”);
context.Writer.WriteInt32((值为Zebra.StripesAmount);
打破
违约:
打破
}
context.Writer.WriteEndDocument();
}
public override Animal反序列化(MongoDB.Bson.Serialization.BsonDeserializationContext,MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
context.Reader.ReadStartDocument();
ObjectId=context.Reader.ReadObjectId();
string object_type=context.Reader.ReadString();
string animal_name=context.Reader.ReadString();
开关(对象类型)
{
“老虎”案:
double tiger_height=context.Reader.ReadDouble();
context.Reader.ReadEndDocument();
返回新老虎()
{
Id=Id,
名称=动物名称,
高度=老虎的高度
};
违约:
长斑马线=context.Reader.ReadInt64();
context.Reader.ReadEndDocument();
返回新斑马()
{
Id=Id,
名称=动物名称,
条纹安装=斑马纹
};
}
返回null;
}
}
它工作得很好,也允许我这样做:

MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Animal), new MyAnimalSerializer());
IMongoCollection<Animal> collection = db.GetCollection<Animal>("animals");
var lst = await collection.Find<Animal>(new BsonDocument()).ToListAsync();
MongoDB.Bson.Serialization.BsonSerializer.RegisterSerializer(typeof(Animal),new MyAnimalSerializer());
IMongoCollection=db.GetCollection(“动物”);
var lst=await collection.Find(new BsonDocument()).toListSync();
但是当动物被存放在动物园时,我不能做同样的事情 无法从动物园集合反序列化动物园:

IMongoCollection<Zoo> collection = db.GetCollection<Zoo>("zoocollection");
var lst = await collection.Find<Zoo>(new BsonDocument()).ToListAsync(); //not working here
IMongoCollection=db.GetCollection(“zoocollection”);
var lst=await collection.Find(new BsonDocument()).toListSync()//不在这里工作
是否可以为字段创建自定义集合序列化程序?

public List<Animal> Animals { get; set; }
公共列表动物{get;set;}
有人能举个例子吗? 提前谢谢

您访问过这个页面吗?也有多态类的例子

下面是我存储对象的示例:

public class Zoo
{
    [BsonId]
    public ObjectId Id { get; set; }
    public List<Animal> Animals { get; set; }
}

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(Tiger), typeof(Zebra))]
public class Animal
{
    [BsonId]
    public ObjectId Id { get; set; }
    public string Name { get; set; }
}

public class Tiger : Animal
{
    public double Height { get; set; }
}
public class Zebra : Animal
{
    public long StripesAmount { get; set; }
}

public class MongoDocumentsDatabase
{
    /// <summary>
    /// MongoDB Server
    /// </summary>
    private readonly MongoClient _client;

    /// <summary>
    /// Name of database 
    /// </summary>
    private readonly string _databaseName;

    public MongoUrl MongoUrl { get; private set; }

    /// <summary>
    /// Opens connection to MongoDB Server
    /// </summary>
    public MongoDocumentsDatabase(String connectionString)
    {
        MongoUrl = MongoUrl.Create(connectionString);
        _databaseName = MongoUrl.DatabaseName;
        _client = new MongoClient(connectionString);
    }

    /// <summary>
    /// Get database
    /// </summary>
    public IMongoDatabase Database
    {
        get { return _client.GetDatabase(_databaseName); }
    }
    public IMongoCollection<Zoo> Zoo { get { return Database.GetCollection<Zoo>("zoo"); } }
}
class Program
{
    static void Main(string[] args)
    {
        var connectionString =
            "mongodb://admin:admin@localhost:27017/testDatabase";
        var pr = new Program();

        pr.Save(connectionString);
        var zoo = pr.Get(connectionString);

        foreach (var animal in zoo.Animals)
        {
            Console.WriteLine(animal.Name + "  " + animal.GetType());
        }
    }


    public void Save(string connectionString)
    {
        var zoo = new Zoo
        {
            Animals = new List<Animal>
            {
                new Tiger
                {
                    Height = 1,
                    Name = "Tiger1"
                },
                new Zebra
                {
                    Name = "Zebra1",
                    StripesAmount = 100
                }
            }
        };

        var database = new MongoDocumentsDatabase(connectionString);
        database.Zoo.InsertOneAsync(zoo).Wait();
    }

    public Zoo Get(string connectionString)
    {
        var database = new MongoDocumentsDatabase(connectionString);
        var task = database.Zoo.Find(e => true).SingleAsync();
        task.Wait();

        return task.Result;
    }
}
公共类动物园
{
[BsonId]
公共对象Id{get;set;}
公共列表动物{get;set;}
}
[BsonDiscriminator(RootClass=true)]
[BsonKnownTypes(虎型、斑马型))]
公营动物
{
[BsonId]
公共对象Id{get;set;}
公共字符串名称{get;set;}
}
公营老虎:动物
{
公共双倍高度{get;set;}
}
公共级斑马:动物
{
公共长条带装入{get;set;}
}
公共类MongoDocumentsDatabase
{
/// 
///MongoDB服务器
/// 
私有只读MongoClient\u客户端;
/// 
///数据库名称
/// 
私有只读字符串_databaseName;
public MongoUrl MongoUrl{get;private set;}
/// 
///打开与MongoDB服务器的连接
/// 
公共MongoDocumentsDatabase(字符串连接字符串)
{
MongoUrl=MongoUrl.Create(connectionString);
_databaseName=MongoUrl.databaseName;
_客户端=新的MongoClient(connectionString);
}
/// 
///获取数据库
/// 
公共数据库
{
获取{return _client.GetDatabase(_databaseName);}
}
公共IMongoCollection动物园{get{return Database.GetCollection(“动物园”);}
}
班级计划
{
静态void Main(字符串[]参数)
{
变量连接字符串=
"mongodb://admin:admin@localhost:27017/testDatabase”;
var pr=新程序();
pr.Save(连接字符串);
var zoo=pr.Get(connectionString);
foreach(动物园里的动物,动物)
{
Console.WriteLine(animal.Name+“”+animal.GetType());
}
}
公共void保存(字符串连接字符串)
{
新动物园
{
动物=新列表
{
新老虎
{
高度=1,
Name=“老虎1”
},
新斑马
{
Name=“Zebra1”,
条带数量=100
}
}
};
var数据库=新的MongoDocumentsDatabase(connectionString);
database.Zoo.InsertOneAsync(Zoo.Wait();
}
公共动物园获取(字符串连接字符串)
{
var数据库=新的MongoDocumentsDatabase(connectionString);
public class Zoo
{
    [BsonId]
    public ObjectId Id { get; set; }
    public List<Animal> Animals { get; set; }
}

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(Tiger), typeof(Zebra))]
public class Animal
{
    [BsonId]
    public ObjectId Id { get; set; }
    public string Name { get; set; }
}

public class Tiger : Animal
{
    public double Height { get; set; }
}
public class Zebra : Animal
{
    public long StripesAmount { get; set; }
}

public class MongoDocumentsDatabase
{
    /// <summary>
    /// MongoDB Server
    /// </summary>
    private readonly MongoClient _client;

    /// <summary>
    /// Name of database 
    /// </summary>
    private readonly string _databaseName;

    public MongoUrl MongoUrl { get; private set; }

    /// <summary>
    /// Opens connection to MongoDB Server
    /// </summary>
    public MongoDocumentsDatabase(String connectionString)
    {
        MongoUrl = MongoUrl.Create(connectionString);
        _databaseName = MongoUrl.DatabaseName;
        _client = new MongoClient(connectionString);
    }

    /// <summary>
    /// Get database
    /// </summary>
    public IMongoDatabase Database
    {
        get { return _client.GetDatabase(_databaseName); }
    }
    public IMongoCollection<Zoo> Zoo { get { return Database.GetCollection<Zoo>("zoo"); } }
}
class Program
{
    static void Main(string[] args)
    {
        var connectionString =
            "mongodb://admin:admin@localhost:27017/testDatabase";
        var pr = new Program();

        pr.Save(connectionString);
        var zoo = pr.Get(connectionString);

        foreach (var animal in zoo.Animals)
        {
            Console.WriteLine(animal.Name + "  " + animal.GetType());
        }
    }


    public void Save(string connectionString)
    {
        var zoo = new Zoo
        {
            Animals = new List<Animal>
            {
                new Tiger
                {
                    Height = 1,
                    Name = "Tiger1"
                },
                new Zebra
                {
                    Name = "Zebra1",
                    StripesAmount = 100
                }
            }
        };

        var database = new MongoDocumentsDatabase(connectionString);
        database.Zoo.InsertOneAsync(zoo).Wait();
    }

    public Zoo Get(string connectionString)
    {
        var database = new MongoDocumentsDatabase(connectionString);
        var task = database.Zoo.Find(e => true).SingleAsync();
        task.Wait();

        return task.Result;
    }
}
public class MyListAnimalSerializer : SerializerBase<List<Animals>>
{
    public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, List<Animal> 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<Animals> Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
    {
        context.Reader.ReadStartArray();

        List<Animals> result = new List<Animals>();

        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.ReadString();
            var _id = context.Reader.ReadObjectId();
            var name = context.Reader.ReadString();
            if (type == "Tiger")
            {
                double tiger_height = context.Reader.ReadDouble();
                result.Add(new Tiger()
                {
                    Id = id,
                    Name = animal_name,
                    Height = tiger_height
                });
            }
            else
            {
                long zebra_stripes = context.Reader.ReadInt64();
                result.Add(return new Zebra()
                {
                    Id = id,
                    Name = animal_name,
                    StripesAmount = zebra_stripes
                });
            }
            context.Reader.ReadEndDocument();
        }
        return result;
    }
}
[BsonSerializer(typeof(MyListAnimalSerializer))]
public List<Animal> Animals { get; set; }
public override List<Animals> Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
{
    context.Reader.ReadStartArray();
    context.Reader.ReadBSonType();

    List<Animals> result = new List<Animals>();

    while (context.Reader.State != MongoDB.Bson.IO.BsonReaderState.EndOfArray)
    {
        context.Reader.ReadStartDocument();

        var type = context.Reader.ReadString();
        var _id = context.Reader.ReadObjectId();
        var name = context.Reader.ReadString();
        if (type == "Tiger")
        {
            double tiger_height = context.Reader.ReadDouble();
            result.Add(new Tiger()
            {
                Id = id,
                Name = animal_name,
                Height = tiger_height
            });
        }
        else
        {
            long zebra_stripes = context.Reader.ReadInt64();
            result.Add(return new Zebra()
            {
                Id = id,
                Name = animal_name,
                StripesAmount = zebra_stripes
            });
        }
        context.Reader.ReadEndDocument();
        context.Reader.ReadBsonType();
    }

    context.Reader.ReadEndArray();

    return result;
}