C# problem with Xml Serialization

Started by
9 comments, last by cyansoft 15 years, 7 months ago
Hi, I'm working on a project that requires storing and restoring settings from an Xml file. Unfortunately it seems .NET's XmlSerializer only likes fully public members, because everytime I use private, protected or internal, either it doesn't write the value at all, or I get a CS0272 error. I also tried readonly, it worked, but wrote a bunch of garbage to the file along with the value. Does anyone know a way to keep the setters for members private and still use Xml serialization? I've searched google and someone suggested using InternalsVisibleTo on System.Xml, but I haven't gotten that to work either. Please help, I don't want to have to reinvent the wheel. Here's the code:

namespace Bob
{
	
	public abstract class TextSerializer<T>
	{
		
		[XmlIgnore]
		private readonly XmlSerializer XmlSerializer = new XmlSerializer( typeof( T ) );
		
		public void Serialize( IO.Stream stream )
		{
			XmlSerializer.Serialize( stream, this );
			return;
		}
		
		public T Deserialize( IO.Stream stream )
		{
			return (T)XmlSerializer.Deserialize( stream );	
		}
		
	}
	
	[XmlRoot("SerialPort")]
	public class SerialPort : TextSerializer<SerialPort>
	{
		
		[XmlElement("BaudRate")]	
		public int BaudRate { get; set; } // private set does not work
		
		[XmlElement("Name")]
		public string Name { get; set; }
		
		public SerialPort()
		{
			return;
		}
		
		public SerialPort( string name, int baudRate )
		{
			Name = name;
			BaudRate = baudRate;
			return;
		}
		
	}

}

Advertisement
Xml.Serializer only serialises/deserialises public members and properties by design. I don't think there's a way to override this behaviour - the various XmlAttributes only work on public members and properties. You may just have to change your design a bit so that you can work with just public members.
NextWar: The Quest for Earth available now for Windows Phone 7.
Yes I could just use public members, but I don't want to. I consider it bad practive and I'm pretty sure MS does as well. I don't understand why it acts this way, the binary serializer works with non-public data, why can't the XML one?
Quote:Original post by Scet
Yes I could just use public members, but I don't want to. I consider it bad practive and I'm pretty sure MS does as well. I don't understand why it acts this way, the binary serializer works with non-public data, why can't the XML one?

Because the XML complement of the Binary serializer is the SOAP Serializer, not the XML Serializer.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:Original post by Scet
I don't understand why it acts this way, the binary serializer works with non-public data, why can't the XML one?


The binary and XML serializers are completely different classes. They don't even implement the same interface. Technically, the BinaryFormatter is a formatter class, designed to completely serialize or deserialize an entire object graph.

On the other hand the XmlSerializer class is for the purpose of serializing or deserializing public properties and fields only. Certain types of collections such as List<T> are not supported by this class.

You might want to look into the DataContractAttribute class. It can use private fields. It has an example of using it along with the XmlDictionaryWriter and XmlDictionaryReader classes to serialize and deserialze an object to/from XML. Note you will need .Net 3.0 or higher to use these classes.
Quote:Original post by Scet
Yes I could just use public members, but I don't want to. I consider it bad practive and I'm pretty sure MS does as well. I don't understand why it acts this way, the binary serializer works with non-public data, why can't the XML one?


I usually have classes that serves no purpose except storing, serializing and deserializing data that sit within another class that actually uses the data and keeps it from being edited incorrectly.
Quote:Original post by cyansoft
Quote:Original post by Scet
I don't understand why it acts this way, the binary serializer works with non-public data, why can't the XML one?


The binary and XML serializers are completely different classes. They don't even implement the same interface. Technically, the BinaryFormatter is a formatter class, designed to completely serialize or deserialize an entire object graph.

On the other hand the XmlSerializer class is for the purpose of serializing or deserializing public properties and fields only. Certain types of collections such as List<T> are not supported by this class.

You might want to look into the DataContractAttribute class. It can use private fields. It has an example of using it along with the XmlDictionaryWriter and XmlDictionaryReader classes to serialize and deserialze an object to/from XML. Note you will need .Net 3.0 or higher to use these classes.


The Xml Serializer can serialize lists.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

This way you can serialize anything you'd like.
Quote:Original post by mpipe
The Xml Serializer can serialize lists.


According to Microsoft, it can't:

Quote:
Serialization of ArrayList and Generic List
The XmlSerializer cannot serialize or deserialize the following:
  • Arrays of ArrayList
  • Arrays of List(T)



Quote:Original post by ernow
http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

This way you can serialize anything you'd like.

Serialize anything you'd like in XML only. If you need to support other formats, you need to use the classes in the System.Runtime.Serialization namespace. If you only need XML, use the IXmlSerializable interface as suggested by ernow as it it's much easier to use than the more flexible alternatives.

Quote:Original post by cyansoft
Quote:Original post by mpipe
The Xml Serializer can serialize lists.


According to Microsoft, it can't:

Quote:
Serialization of ArrayList and Generic List
The XmlSerializer cannot serialize or deserialize the following:
  • Arrays of ArrayList
  • Arrays of List(T)


It can't serialize arrays of lists, but it can most certainly serialize individual lists. I know this for a fact to be true, since I'm using XmlSerializer to serialize List<string> at work, among other things. However I also know for a fact that it can't serialize dictionaries or hashtables, which I'm still a little peeved about (but managed to get around by using a special accessor).

This topic is closed to new replies.

Advertisement