繁体   English   中英

在 MongoDB 中为嵌套的 object 使用自定义序列化程序会干扰使用该 object 的过滤器

[英]Using a custom serializer in MongoDB for a nested object interferes with filters using that object

我有如下定义的模型(我省略了与问题没有直接关系的部分):

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:不支持转换({document}{State}.Representation,Int32)。

很明显,序列化程序是罪魁祸首,因为当我删除SetSerializer调用时,一切正常。 您可能会说我在做的事情看起来很奇怪,但是请理解上面的AbstractState实现是最小版本 - 实际上它有更多代码,并且需要以 MongoDB 无法运行的方式初始化代码。 我的目标是有一个干净的聚合 - 只包含业务逻辑而不是构造逻辑。 这就是为什么我宁愿有一些基础设施代码(如自定义序列化程序)来初始化 state object。 关于如何使其工作的任何想法?

成功的关键是实现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;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM