#c# #mongodb
Вопрос:
Во время выполнения некоторых технических задач и в учебных целях я хотел бы написать свой собственный сериализатор для базы данных mongodb. Насколько я знаю, мне нужно реализовать интерфейс IBsonArraySerializer
.
Чтобы иметь небольшой пример, представьте себе следующее poco:
public class Foo
{
[BsonSerializer(typeof(MyCustomArraySerializer))]
public List<Bar> BarList {get; set;}
}
public class Bar
{
public string Name {get; set;}
}
public class MyCustomArraySerializer: IBsonArraySerializer //, IBsonDocumentSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
throw new NotImplementedException();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
throw new NotImplementedException();
}
public Type ValueType { get; }
public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
{
throw new NotImplementedException();
}
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
{
serializationInfo = null
return true;
}
}
Как вы можете видеть, это только начало реализации. Проблема в настоящее время заключается в том, что, похоже, сериализатор не используется, если я просто найду в базе данных документ:
Смотрите мою дорожку стека:
System.NullReferenceException: Object reference not set to an instance of an object.
at MongoDB.Bson.Serialization.BsonMemberMap.SetSerializer(IBsonSerializer serializer)
at MongoDB.Bson.Serialization.Attributes.BsonSerializerAttribute.Apply(BsonMemberMap memberMap)
at MongoDB.Bson.Serialization.Conventions.AttributeConventionPack.AttributeConvention.Apply(BsonMemberMap memberMap)
at MongoDB.Bson.Serialization.Conventions.ConventionRunner.Apply(BsonClassMap classMap)
at MongoDB.Bson.Serialization.BsonClassMap.AutoMapClass()
at MongoDB.Bson.Serialization.BsonClassMap.AutoMap()
at MongoDB.Bson.Serialization.BsonClassMap.LookupClassMap(Type classType)
at MongoDB.Bson.Serialization.BsonClassMapSerializationProvider.GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Bson.Serialization.BsonSerializerRegistry.CreateSerializer(Type type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at MongoDB.Bson.Serialization.BsonSerializerRegistry.GetSerializer(Type type)
at MongoDB.Bson.Serialization.BsonSerializerRegistry.GetSerializer[T]()
at MongoDB.Driver.MongoCollectionImpl`1..ctor(IMongoDatabase database, CollectionNamespace collectionNamespace, MongoCollectionSettings settings, ICluster cluster, I
OperationExecutor operationExecutor)
at MongoDB.Driver.MongoDatabaseImpl.GetCollection[TDocument](String name, MongoCollectionSettings settings)
at Shared.Mongo.MongoService.GetCollection[T](String collectionName)
То, что я ищу, было бы рабочим примером или некоторой помощью, чтобы начать эту работу. Написание сериализатора для одного класса вместо списка с некоторыми классами не было проблемой.
Ответ №1:
как насчет чего-нибудь вроде этого:
public class MyCustomArraySerializer : SerializerBase<List<Bar>>, IBsonArraySerializer
{
private static readonly IBsonSerializer<Bar> itemSerializer = BsonSerializer.LookupSerializer<Bar>();
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, List<Bar> list)
{
ctx.Writer.WriteStartArray();
if (list is null)
{
ctx.Writer.WriteEndArray();
return;
}
foreach (var item in list)
{
itemSerializer.Serialize(ctx, item);
}
ctx.Writer.WriteEndArray();
}
public override List<Bar> Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
switch (ctx.Reader.CurrentBsonType)
{
case BsonType.Array:
var list = new List<Bar>();
ctx.Reader.ReadStartArray();
while (ctx.Reader.ReadBsonType() != BsonType.EndOfDocument)
list.Add(itemSerializer.Deserialize(ctx));
ctx.Reader.ReadEndArray();
return list;
case BsonType.Null:
ctx.Reader.ReadNull();
return null;
default:
throw new SerializationException("Cannot deserialize!");
}
}
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
{
serializationInfo = new BsonSerializationInfo(null, itemSerializer, itemSerializer.ValueType);
return true;
}
}