mono支持带有preserveObjectReferences标志的DataContractSerializer吗?

时间:2010-07-19 12:54:18

标签: c# serialization mono

我正在尝试使用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支持这些构造函数。

1 个答案:

答案 0 :(得分:6)

编辑:从我看到你还需要在DataContractAttribute中设置IsReference = true属性,请参阅herehere

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*/);