Serialization in C # with a derived class

I create a notification structure, and for this I serialize and deserialize the base class from which all the classes that I want to send will be received.

The problem is that the code is compiling, but when I actually try to serialize this base class, I get an error

System.Runtime.Serialization.SerializationException: Type 'Xxx.DataContracts.WQAllocationUpdate' in Assembly 'Xxx.DataContract, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null' is not marked as serializable.

Here is the code:

public class WCallUpdate : NotificationData { private string m_from = ""; [DataMember] public string From { get { return m_from; } set { m_from = value; } } private WCall m_wCall = new WCall(); [DataMember] public WCall Call { get { return m_wCall; } set { m_wCall = value; } } } 

DataContract for notification:

 /// <summary> /// Basic class used in the notification service /// </summary> [DataContract] public class NotificationData { } /// <summary> /// Enum containing all the events used in the application /// </summary> [DataContract] public enum NotificationTypeKey { [EnumMember] Default = 0, [EnumMember] IWorkQueueServiceAttributionAddedEvent = 1, [EnumMember] IWorkQueueServiceAttributionUpdatedEvent = 2, [EnumMember] IWorkQueueServiceAttributionRemovedEvent = 3, } 

Code used to serialize data:

  #region Create Message /// <summary> /// Creates a memoryStream from a notificationData /// note: we insert also the notificationTypeKey at the beginning of the /// stream in order to treat the memoryStream correctly on the client side /// </summary> /// <param name="notificationTypeKey"></param> /// <param name="notificationData"></param> /// <returns></returns> public MemoryStream CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData) { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); try { formatter.Serialize(stream, notificationTypeKey); formatter.Serialize(stream, notificationData); } catch (Exception ex) { Logger.Exception(ex); } return stream; } #endregion 

When I try to create a message:

 WCallUpdate m_wCallUpdate = new WCallUpdate(); NotificationTypeKey m_notificationTypeKey = new NotificationTypeKey.Default; CreateMessage(notificationTypeKey , wCallUpdate ); 

I got the following error:

 System.Runtime.Serialization.SerializationException: Type 'Xxx.DataContracts.WCall' in Assembly 'Xxx.DataContract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) at Xxx.Notification.NotificationMessageFactory.CreateMessage(NotificationTypeKey notificationTypeKey, NotificationData notificationData) in Xxx.Notification\NotificationCenter.cs:line 36 

If I put the Serializable flag in front of the DataContract , it does not solve the problem.


Thank you for your prompt reply. Sorry I forgot to put the NotificationData code (edited in the main post)

I tried to put the Serializable attribute in both classes without success :(

 #region NotificationData /// <summary> /// Basic class used in the notification service /// </summary> [Serializable] [DataContract] public class NotificationData { } #endregion 

and

 [Serializable] public class WCallUpdate : NotificationData { private string m_from = ""; [DataMember] public string From { get { return m_from; } set { m_from = value; } } private WCall m_wCall = new WCall(); [DataMember] public WCall Call { get { return m_wCall; } set { m_wCall = value; } } } 

** Edit: ** Mea culpa afterall :) You were both right. I forgot to distribute the [Serializable] attribute to the entire child class. After updating and compiling, I was no longer an exception. Thank you for your correct answers :)


@Marc Gravel: Actually, I was thinking about what you are offering and created the following DataContractSerializer, but I'm not sure if this will work? How do my classes use other classes? the big problem with the DataContractSerializer is that you need to specify the type of object you want to serialize, and since my class uses another class as private fields, can this cause the problem correctly?

 #region DataContractSerializer /// <summary> /// Creates a Data Contract Serializer for the provided type. The type must be marked with /// the data contract attribute to be serialized successfully. /// </summary> /// <typeparam name="T">The type to be serialized</typeparam> /// <returns>A data contract serializer</returns> public static DataContractSerializer CreateDataContractSerializer<T>() where T : class { DataContractSerializer serializer = new DataContractSerializer(typeof(T)); return serializer; } #endregion 
+4
source share
4 answers

put [Serializable] at the top of the class. Serializable is not necessarily inherited by either AFAIK. this means that even if the base class has [Serializable], it still needs a descendant class.

+18
source

I am very confused why you are using BinaryFormatter with a data contract. It would be ok to use the DataContractSerializer here ... the logic then is similar to using [Serializable] , except for the need for [DataContract ], and it serializes the assigned ( [DataMember] ) elements, not the fields that BinaryFormatter works with.

Actually, for numerous reasons ( for example, fragility ) I would suggest switching to a DataContractSerializer , especially since this seems to be your intention, Or, if you need a more compact binary form, protobuf-net can be useful (plus it is portable between platforms too).

Aside - you do not need [DataContract] on enum - it does no harm, but also not very much.

+6
source

To get the class to be serialized, mark it with a serializable attribute or deduce it from MarshalByRefObject.

You get from NotificationData, is it serialized?

Also check this: when serializable data classes are put into the assembly, check your project or file link in Visual Studio to make sure you are correct.

Also, if you sign the assembly and put it in the GAC, make sure that the assembly in the GAC is correct! I came across multitasking debugsessions because I updated the assembly from version 1.0.0.0 to 1.0.0.1 and forgot to replace the old one in the GAC. Assemblies in the GAC are loaded before local assemblies, keep this in mind. And ... binary formatting is very strictly related to build versions.

+2
source

I created an XList class to accomplish this:

 AA D1=new AA(); //Derived type BB D2=new BB(); //Derived type CC D3=new CC(); //Derived type X D4=new X(); //Base Class XList<X> AllData=new XList<X>(); AllData.Add(D1); AllData.Add(D2); AllData.Add(D3); AllData.Add(D4); // ----------------------------------- AllData.Save(@"C:\Temp\Demo.xml"); // ----------------------------------- // Retrieve data from XML file // ----------------------------------- XList<X> AllData=new XList<X>(); AllData.Open(@"C:\Temp\Demo.xml"); // ----------------------------------- 

More information can be found here .

0
source

All Articles