我正在尝试使用c#mono(mono v2.6)序列化复杂图形,图形具有双向链接,并且存在创建循环依赖关系的对象。在做了一些阅读之后,我尝试设置了preserveObjectReferences标志,该标志应该允许设置循环引用(这个构造函数):
public DataContractSerializer(
Type type,
IEnumerable<Type> knownTypes,
int maxItemsInObjectGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate
)
我得到的例外情况如下:
SerializationException: Circular reference of an object in the object graph was found: 'ShaderMasterNode' of type ShaderMasterNode
有人在单声道中序列化复杂对象有什么运气吗?根据这里的文件: http://go-mono.com/status/status.aspx?reference=3.5&profile=2.0&assembly=System.Runtime.Serialization支持这些构造函数。
答案 0 :(得分:6)
编辑:从我看到你还需要在DataContractAttribute中设置IsReference = true属性,请参阅here和here
IsReference获取或设置一个值,该值指示是否保留对象引用数据。 PreserveObjectReferences 应该获取一个值,该值指定是否使用非标准XML构造来保留对象引用数据。
Mono确实支持数据合同序列化,但正如源代码中的评论所述,还有一些工作要做:
([MonoTODO(“支持数组;支持Serializable;支持SharedType;使用DataContractSurrogate”)] - preserveObjectReferences指示输出是否应包含ms:Id。)
尝试阅读数据合同序列化here的.NET Framework文档,并将其与Mono中提供的源代码进行比较,这将澄清事情。
对其他System.Runtime.Serialization命名空间也一样,阅读MSDN中的文档并与Mono namespaces中的内容进行比较
Mono中的System.Runtime.Serialization命名空间的源代码可用here,DataContractSerializer类源是here,其中包含以下感兴趣的内容:
// Three constructors with this property
public DataContractSerializer (Type type,
IEnumerable<Type> knownTypes,
int maxObjectsInGraph,
bool ignoreExtensionDataObject,
**bool preserveObjectReferences,**
IDataContractSurrogate dataContractSurrogate)
: this (type, knownTypes)
{
Initialize (maxObjectsInGraph,
ignoreExtensionDataObject,
**preserveObjectReferences,**
dataContractSurrogate);
}
public DataContractSerializer (Type type,
string rootName,
string rootNamespace,
IEnumerable<Type> knownTypes,
int maxObjectsInGraph,
bool ignoreExtensionDataObject,
**bool preserveObjectReferences,**
IDataContractSurrogate dataContractSurrogate)
: this (type, rootName, rootNamespace, knownTypes)
{
Initialize (maxObjectsInGraph,
ignoreExtensionDataObject,
**preserveObjectReferences,**
dataContractSurrogate);
}
public DataContractSerializer (Type type,
XmlDictionaryString rootName,
XmlDictionaryString rootNamespace,
IEnumerable<Type> knownTypes,
int maxObjectsInGraph,
bool ignoreExtensionDataObject,
**bool preserveObjectReferences,**
IDataContractSurrogate dataContractSurrogate)
: this (type, rootName, rootNamespace, knownTypes)
{
Initialize (maxObjectsInGraph,
ignoreExtensionDataObject,
**preserveObjectReferences,**
dataContractSurrogate);
}
// Initialize()方法
void Initialize (
int maxObjectsInGraph,
bool ignoreExtensionDataObject,
bool preserveObjectReferences,
IDataContractSurrogate dataContractSurrogate)
{
if (maxObjectsInGraph < 0)
throw new ArgumentOutOfRangeException ("maxObjectsInGraph must not be negative.");
max_items = maxObjectsInGraph;
ignore_ext = ignoreExtensionDataObject;
preserve_refs = preserveObjectReferences;
surrogate = dataContractSurrogate;
PopulateTypes (Type.EmptyTypes);
}
// preserveObjectReferences()属性
public bool PreserveObjectReferences {
get { return preserve_refs; }
}
根据this:
**默认情况下,DataContractSerializer不保留对象引用; 多次引用的对象的值被多次序列化。如果对象是相互(循环)引用的一部分(例如循环链表),则在序列化期间抛出异常。
可以通过在构造DataContractSerializer时为参数PreserveObjectReference传递true来使DataContractSerializer保留对象引用**:
new DataContractSerializer(type, name, ns, knownTypes,
0x7FFF /*maxObjectsInGraph*/,
false/*ignoreExtensionDataObject*/,
true/*preserveObjectReferences*/,
null/*dataContractSurrogate*/);