C# 在protobuf net中使用代理时,字典中的引用跟踪不起作用
我不想用任何序列化逻辑搞乱我们的BusinessObjects。 这就是为什么我想为每个BusinessObject实现一个代理,它封装了序列化和反序列化BusinessObject所需的数据。 此外,它还包含序列化后要执行的所有业务逻辑 然而,词典中的引用跟踪似乎存在一个问题。考虑下面的例子:C# 在protobuf net中使用代理时,字典中的引用跟踪不起作用,c#,protobuf-net,C#,Protobuf Net,我不想用任何序列化逻辑搞乱我们的BusinessObjects。 这就是为什么我想为每个BusinessObject实现一个代理,它封装了序列化和反序列化BusinessObject所需的数据。 此外,它还包含序列化后要执行的所有业务逻辑 然而,词典中的引用跟踪似乎存在一个问题。考虑下面的例子: //DataContracts: public class SerializeClass { public Dictionary<
//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也得到了同样的例外:我将把它添加到我的第一篇文章中,因为这几个字符不够:对;我有这个例子,稍后再看