简体   繁体   English

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

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

I have models defined like below (I ommited parts not directly related to the problem):我有如下定义的模型(我省略了与问题没有直接关系的部分):

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
}

And the serializer code:和序列化程序代码:

public class AbstractStateSerializer : SerializerBase<AbstractState>
{
    public override AbstractState Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) =>
        StateFactory.CreateFor(base.Deserialize(context, args));
}

And this code is what I use to register the serializer:这段代码是我用来注册序列化程序的:

cm.MapField(c => c.State).SetSerializer(new AbstractStateSerializer());

Now, when I issue a count query agains my MongoDB instance, I get an error saying:现在,当我对我的 MongoDB 实例发出计数查询时,我收到一条错误消息:

System.InvalidOperationException: Convert({document}{State}.Representation, Int32) is not supported. System.InvalidOperationException:不支持转换({document}{State}.Representation,Int32)。

It's obvious that the serializer is to blame, because when I remove the SetSerializer call everything works fine.很明显,序列化程序是罪魁祸首,因为当我删除SetSerializer调用时,一切正常。 You may say that what I'm doing looks weird, however please understand that this AbstractState implementation above is the minimal version - in reality it has a bit more code and that code needs to be initialized in a way that MongoDB can't operate.您可能会说我在做的事情看起来很奇怪,但是请理解上面的AbstractState实现是最小版本 - 实际上它有更多代码,并且需要以 MongoDB 无法运行的方式初始化代码。 My goal here is to have a clean aggregate - holding only the business logic and not the construction logic.我的目标是有一个干净的聚合 - 只包含业务逻辑而不是构造逻辑。 That's why I'd rather have some infrastructural code in place (like that custom serializer) to initialize the state object.这就是为什么我宁愿有一些基础设施代码(如自定义序列化程序)来初始化 state object。 Any ideas on how to make it work?关于如何使其工作的任何想法?

The key to success was to implement the IBsonDocumentSerializer .成功的关键是实现IBsonDocumentSerializer If anyone's interested, my implementation below:如果有人感兴趣,我的实现如下:

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