c# - 在 MongoDB 中为嵌套对象使用自定义序列化程序会干扰使用该对象的过滤器
问题描述
我有如下定义的模型(我省略了与问题没有直接关系的部分):
public class AnObjectWithState {
public AbstractState State { get; private set; }
}
public abstract class AbstractState {
public State Representation { get; protected set; }
}
public enum State {
State1,
State2,
State3
}
和序列化程序代码:
public class AbstractStateSerializer : SerializerBase<AbstractState>
{
public override AbstractState Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
StateFactory.CreateFor(base.Deserialize(context, args));
}
这段代码是我用来注册序列化程序的:
cm.MapField(c => c.State).SetSerializer(new AbstractStateSerializer());
现在,当我对我的 MongoDB 实例发出计数查询时,我收到一条错误消息:
System.InvalidOperationException:不支持 Convert({document}{State}.Representation, Int32)。
很明显,序列化程序是罪魁祸首,因为当我删除SetSerializer
调用时,一切正常。你可能会说我在做的事情看起来很奇怪,但是请理解AbstractState
上面的这个实现是最小的版本——实际上它有更多的代码,并且代码需要以 MongoDB 无法运行的方式进行初始化。我的目标是有一个干净的聚合 - 只包含业务逻辑而不是构造逻辑。这就是为什么我宁愿有一些基础设施代码(如自定义序列化程序)来初始化状态对象。关于如何使其工作的任何想法?
解决方案
成功的关键是实施IBsonDocumentSerializer
. 如果有人感兴趣,我的实现如下:
public class AbstractStateSerializer : SerializerBase<AbstractState>, IBsonDocumentSerializer
{
public override AbstractState Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
context.Reader.ReadStartDocument();
context.Reader.ReadBsonType();
context.Reader.SkipName();
var value = context.Reader.ReadInt32();
context.Reader.ReadEndDocument();
var state = // here I construct a graph of objects based on the above value variable
return state;
}
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, AbstractState value)
{
context.Writer.WriteStartDocument();
context.Writer.WriteName(nameof(value.Representation));
context.Writer.WriteInt32((int)value.Representation);
context.Writer.WriteEndDocument();
}
public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
{
switch (memberName)
{
case "Representation":
serializationInfo = new BsonSerializationInfo("Representation", new EnumSerializer<State>(), typeof(State));
return true;
default:
serializationInfo = null;
return false;
}
}
}
推荐阅读
- vtiger - 项目模块,如何选择默认的“relatedto”字段值
- python - 我们可以使用win32com.client和xlrd在python中使用xlrd.openworkbook中的outlook.attachments对象而不保存excel文件吗
- python - 是否可以矢量化 scipy fsolve?
- c# - 可以在 UWP 中从 C# 代码设置 package.manifest 属性吗?
- ckeditor - 有没有供moono-lisa使用的scss文件
- python - 用于解析文件和建立符号链接的脚本
- windows - 如何使用 azure pipleine 运行代理的命令行或 powershell?
- c - 分配一个下标范围为 v[nl..nh] 的浮点向量
- django - Faker 使用 Factory Boy 创建的所有相等值
- neutrinos-platform - 如何在 Windows 10 中设置该工具?