自定义序列化器导致不能创建抽象类



Mongo自定义序列化器导致无法创建抽象类

嗨,我试图添加一个自定义序列化器到我的mongo类,它似乎不能正常工作。我们的目标是在数据库中有古代事件,我想以一种"新格式"来阅读它们。

但是错误正在与新事件一起发生。这是结构

public abastract class FooBase
{
public int Version { get; set; }
public Guid AggregateId { get; set; }
//Other properties
public abstract object GetContent();
}
public class TypedFooBase<T> : FooBase
where T : class
{
public T TypedContent { get; set; }
//Other properties

public override object GetContent()
{
return TypedContent;
}
}

然后我创建了一个自定义序列化器,如下所示:

public class BsonAncientEventSerializer<T> : SerializerBase<TypedFooBase<T>> where T : class
{
public override TypedFooBase<T> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var serializer = BsonSerializer.LookupSerializer(typeof(ExpandoObject));
var obj = serializer.Deserialize(context);
string valueString = JsonConvert.SerializeObject(obj);
return JsonConvert.DeserializeObject<TypedFooBase<T>>(valueString, new Json.JsonAncientEventSerializer<T>())
?? throw new Exception("something went wrong");
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TypedFooBase<T> value)
{
var bsonWriter = context.Writer;
var fields = value.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public); 
var propsAll = value.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); 
var props = new List<PropertyInfo>(); 
foreach (var prop in propsAll) 
{ 
if (prop.CanWrite) 
{ 
props.Add(prop); 
} 
} 
bsonWriter.WriteStartDocument(); 
foreach (var field in fields) 
{ 
bsonWriter.WriteName(field.Name); 
BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value)); 
} 
foreach (var prop in props) 
{ 
bsonWriter.WriteName(prop.Name); 
BsonSerializer.Serialize(bsonWriter, prop.PropertyType, prop.GetValue(value, null)); 
} 
context.Writer.WriteEndDocument(); 
}
}

然后注册序列化器:

BsonSerializer.RegisterSerializer(
typeof(TypedFooBase<TestEvent>),
new BsonAncientEventSerializer<TestEvent>()
);

如果我不注册序列化器,一切都可以正常工作(除了与旧事件的兼容性)。但是当我添加寄存器序列化器时,代码不能正常工作;

serialize工作正常(值正确存储在数据库中);

但是在读取时,它不起作用。代码根本不会在Deserialize中停止。

我在代码中访问的集合是IMongoCollection<FooBase>;

然后当我做collection.Find(...).ToListAsync()时,它给了我一个错误的Cannot create an abstract class

这是因为它试图将值转换为FooBase;

但是它为什么要这样做呢?为什么,当我不注册序列化器工作正常?

谢谢。

您看到的行为与以下事实有关:您为TypedFooBase<TestEvent>注册了自定义序列化器,但是反序列化期间使用的集合类型是FooBase,因此找不到所需的序列化器。你可以试试:

  • 将序列化器映射到基类型:

    BsonSerializer.RegisterSerializer(
    typeof(FooBase),
    new BsonAncientEventSerializer<TestEvent>()
    

和适当的序列化器定义:

public class BsonAncientEventSerializer<T> : SerializerBase<FooBase> where T : class
  • 理论上,最好的方法是使用合适的类型来获得如下结果:

    var result = collection.OfType<TypedFooBase<TestEvent>>().Find("{}").ToList();
    

,但要使其工作,您需要实现在序列化步骤中跳过的鉴别器行为,因为OfType另外添加了一个_t(鉴别器)过滤器,该过滤器在序列化文档中没有显示。

注意:我没有检查它,但我认为你可以创建一个新的类型(不是基)集合实例(它本身不做任何服务器请求),只用于查找操作:IMongoCollection<TypedFooBase<TestEvent>>

  • 另外,你可以看看这个doc

  • 更新:听起来是这样的:

    var result = coll.FindSync("{}", new FindOptions<FooBase, TypedFooBase<TestEvent>>()).ToList();
    

也可以。

最新更新