C# 在protobuf net中使用代理时,字典中的引用跟踪不起作用

C# 在protobuf net中使用代理时,字典中的引用跟踪不起作用,c#,protobuf-net,C#,Protobuf Net,我不想用任何序列化逻辑搞乱我们的BusinessObjects。 这就是为什么我想为每个BusinessObject实现一个代理,它封装了序列化和反序列化BusinessObject所需的数据。 此外,它还包含序列化后要执行的所有业务逻辑 然而,词典中的引用跟踪似乎存在一个问题。考虑下面的例子: //DataContracts: public class SerializeClass { public Dictionary<

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

然而,词典中的引用跟踪似乎存在一个问题。考虑下面的例子:

   //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];
                }
这两个是相等的。。。反序列化后布尔值应为真。但是,我在反序列化过程中遇到以下异常:

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

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

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

顺便说一句,我使用的是protobuf net v2 429

/编辑2: 使用此代码也可以引发此异常,它根本不需要字典:

    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

我得晚点再看。。。只要它在反序列化过程中只对该项进行了一次,在字典中,我想不出它不能工作的原因-更可能的是,这是一个边缘情况,它正在做一些事情。。。不可靠。非常感谢您的快速回复。我想在此期间我会试试v1。我现在正试图说服我们的项目负责人从BinaryFormatter切换到您的库。然而,很快我就必须能够展示第一个工作原型;v1根本没有参考跟踪;即使不使用字典,pI也得到了同样的例外:我将把它添加到我的第一篇文章中,因为这几个字符不够:对;我有这个例子,稍后再看