views:

85

answers:

1

Hi all,

I am trying to serialize a complex graph using c# mono (mono v2.6) the graph has bi-directional links and there are objects which create circular dependencies. After doing some reading I tried setting the preserveObjectReferences flag which should allow circular references to be set (this constructor):

public DataContractSerializer(
 Type type,
 IEnumerable<Type> knownTypes,
 int maxItemsInObjectGraph,
 bool ignoreExtensionDataObject,
 bool preserveObjectReferences,
 IDataContractSurrogate dataContractSurrogate
)

The exception I get is as follows:

SerializationException: Circular reference of an object in the object graph was found: 'ShaderMasterNode' of type ShaderMasterNode

Has anyone had any luck serializing complex objects in mono? According to the documentation here: http://go-mono.com/status/status.aspx?reference=3.5&amp;profile=2.0&amp;assembly=System.Runtime.Serialization These constructors are supported.

+1  A: 

EDIT: From what I see you also need to set the IsReference = true property in the DataContractAttribute , see here and here

IsReference gets or sets a value that indicates whether to preserve object reference data. PreserveObjectReferences should get a value that specifies whether to use non-standard XML constructs to preserve object reference data.

Mono does support Data Contract Serialization but as this comment made in the source tells, there is some work to be done :

([MonoTODO ("support arrays; support Serializable; support SharedType; use DataContractSurrogate")] - preserveObjectReferences indicates that whether the output should contain ms:Id or not. )

Try to read the .NET Framework documentation for Data Contract Serialization here and compare it with the source code available in Mono, this will clarify things.

Also do the same for other System.Runtime.Serialization Namespaces, read the documentation from MSDN and compare with what you got in Mono namespaces

The source code for System.Runtime.Serialization Namespaces in Mono is available here and the DataContractSerializer Class source is here which contains the following things that interest:

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

// the Initialize() method

    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);
  }

// the preserveObjectReferences() property

    public bool PreserveObjectReferences {
   get { return preserve_refs; }
  }

According to this:

**By default object references are not preserved by the DataContractSerializer; Values of an object referenced multiple times is serialized multiple times. If the object is part of mutual (cyclic) reference (e.g. circular linked list) an exception is thrown during serialization.

DataContractSerializer can be made to preserve object reference by passing true for parameter PreserveObjectReference when constructing DataContractSerializer** :

new DataContractSerializer(type, name, ns, knownTypes,
            0x7FFF /*maxObjectsInGraph*/,
            false/*ignoreExtensionDataObject*/,
            true/*preserveObjectReferences*/,
            null/*dataContractSurrogate*/);
Alex Butum