Sign in to follow this  
Scet

C# problem with Xml Serialization

Recommended Posts

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

}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
Quote:
Original post by Zipster
Quote:
Original post by cyansoft

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.

Oops, you're right. I read that way too fast.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this