使用带有protobuf-net的代理时,字典中的参考跟踪不起作用

时间:2011-07-11 14:15:15

标签: c# protobuf-net

我不想用任何序列化逻辑搞乱我们的BusinessObjects。 这就是为什么我想为每个单独的BusinessObject实现一个Surrogate,它封装了序列化和反序列化BusinessObject所必需的Data。 此外,它包含序列化后要执行的所有业务逻辑。

然而,词典中的引用跟踪似乎存在问题。请考虑以下示例:

   //DataContracts:


        public class SerializeClass
        {
            public Dictionary<string, SerializeDictionaryItem> MyDictionary { get; set; }
            public List<SerializeDictionaryItem> MyList { get; set; }
        }

        [ProtoContract]
        public class SerializeDictionaryItem
        {
            [ProtoMember(1)]
            public string MyField { get; set; }
        }

            [ProtoContract(SkipConstructor = true)]
            public class SerializeClassSurrogate
            {
                [ProtoMember(1000, AsReference = true)]
                public Dictionary<string, SerializeDictionaryItem> MyDictionary { get; set; }

                [ProtoMember(1001, AsReference = true)]
                public List<SerializeDictionaryItem> MyList { get; set; }

                public static implicit operator SerializeClass(SerializeClassSurrogate surrogate)
                {
                    if (surrogate == null)
                        return null;

                    var serializeClass = new SerializeClass();
                    serializeClass.MyDictionary = surrogate.MyDictionary;
                    serializeClass.MyList = surrogate.MyList;

                    return serializeClass;
                }

                public static implicit operator SerializeClassSurrogate(SerializeClass serializeClass)
                {
                    if (serializeClass == null)
                        return null;

                    var surrogate = new SerializeClassSurrogate();
                    surrogate.MyDictionary = serializeClass.MyDictionary;
                    surrogate.MyList = serializeClass.MyList;

                    return surrogate;
                }
            }


    //Serialization Logic:
RuntimeTypeModel.Default[typeof(SerializeClass)].SetSurrogate(typeof(Surrogates.SerializeClassSurrogate));

                var myDictionaryItem = new SerializeDictionaryItem();
                myDictionaryItem.MyField = "ABC";

                SerializeClass m = new SerializeClass() {MyDictionary = new Dictionary<string, SerializeDictionaryItem>()};
                m.MyDictionary.Add("def", myDictionaryItem);
                m.MyDictionary.Add("abc", myDictionaryItem);

                m.MyList = new List<SerializeDictionaryItem>();
                m.MyList.Add(myDictionaryItem);
                m.MyList.Add(myDictionaryItem);

                using (var writer = new StreamWriter(OutputDir + "proto.bin"))
                {
                    Serializer.Serialize(writer.BaseStream, m);
                }

                using(var reader = new StreamReader(OutputDir + "proto.bin"))
                {
                    var deserialized = Serializer.Deserialize<SerializeClass>(reader.BaseStream);
                    var areEqualInDictionary = deserialized.MyDictionary["def"] == deserialized.MyDictionary["abc"];
                    var areEqualInList = deserialized.MyList[0] == deserialized.MyList[1];
                }

反序列化后,两个“areEqualIn ...”布尔应该是真的。但是,在反序列化期间,我得到以下异常:

“在反序列化期间,引用跟踪对象更改了引用”

这是一个错误还是我做错了什么?

/编辑: 这似乎与代理人的使用没有任何关系。如果我在没有它们的情况下尝试序列化,只需将SerializeClass更改为ProtoContract,并将其成员相应地更改为ProtoMembers,就会出现同样的问题。

顺便说一下。我正在使用protobuf-net v2 429

/ EDIT2: 也可以使用此代码激发此异常,该代码根本不需要字典:

    public class SerializeClass
    {
        public string MyField { get; set; }

        public SerializeClass GroupTrailerRef { get; set; }
    }

        [ProtoContract(SkipConstructor = true)]
        public class SerializeClassSurrogate
        {
            [ProtoMember(1001)]
            public string MyField { get; set; }

            [ProtoMember(1002, AsReference = true)]
            public SerializeClass GroupTrailerRef { get; set; }

            public static implicit operator SerializeClass(SerializeClassSurrogate surrogate)
            {
                if (surrogate == null)
                    return null;

                var serializeClass = new SerializeClass();
                serializeClass.MyField = surrogate.MyField;
                serializeClass.GroupTrailerRef = surrogate.GroupTrailerRef;

                return serializeClass;
            }

            public static implicit operator SerializeClassSurrogate(SerializeClass serializeClass)
            {
                if (serializeClass == null)
                    return null;

                var surrogate = new SerializeClassSurrogate();
                surrogate.MyField = serializeClass.MyField;
                surrogate.GroupTrailerRef = serializeClass.GroupTrailerRef;

                return surrogate;
            }
        }

RuntimeTypeModel.Default[typeof(SerializeClass)].SetSurrogate(typeof(Surrogates.SerializeClassSurrogate));

//Serialization Code:
SerializeClass groupTrailer = new SerializeClass();
            groupTrailer.MyField = "Group";

            SerializeClass m = new SerializeClass() {};
            m.GroupTrailerRef = groupTrailer;
            m.MyField = "First";

            SerializeClass k = new SerializeClass();
            k.GroupTrailerRef = groupTrailer;
            k.MyField = "Second";


            var lst = new List<SerializeClass>();
            lst.Add(m);
            lst.Add(k);

            using (var writer = new StreamWriter(OutputDir + "proto.bin"))
            {
                Serializer.Serialize(writer.BaseStream, lst);
            }

            using(var reader = new StreamReader(OutputDir + "proto.bin"))
            {
                var deserialized = Serializer.Deserialize<List<SerializeClass>>(reader.BaseStream);
                var areEqual = deserialized[0].GroupTrailerRef == deserialized[1].GroupTrailerRef;
            }

你有什么建议?我喜欢使用代理方法将序列化逻辑与业务对象分开。你认为我应该坚持“正常”的方式吗?但是在那种情况下,由于问题203 ......我再次陷入困境。

谢谢你, TH

0 个答案:

没有答案