XmlSerializer on properties and indexers containing private fields, how to do?

  • Thread starter Thread starter Beorne
  • Start date Start date
B

Beorne

I have to use XmlSerializer to serialize a class and I've found big
problems serializing properties and indexers.

I assumed that if you serialize a class with public properties (or an
indexers) containing a field, even private, the serialization process
would serialize that field too assuming it is needed to that public
property. This is not the case ...
For example I want to serialize the following class:

[Serializable]
public class Test
{
readonly int[] a; // same results with private
readonly int b; // same results with private

public Test(int[] v1, int b)
{
a = v1;
b = v2;
}

public Test() : this(new int[] {10, 10}, 50) { }

public int this[int i]
{
get { return a; }
set { a = value; }
}

public bool b100
{
get { return b > 100; }
set { }
}

}

I serialize it after constructing it with

Test test = new Test(new int[] { 30, 30 }, 200);

the resulting xml contains:

<test>
<b100>true</b100>
</test>

that is not useful in any way.

If I change the readonly (or private, it is the same) members class to
public the resulting xml contains:
<test>
<a>
<int>30</int>
<int>30</int>
</a>
<b>200</b>
<b100>true</b100>
</test>

That is what I want.

Finally the question: how can I serialize my classes without having to
make all fields public and without using simple expose properties like

public int A
{
get { return a; }
set { a = value; }
}

???

Thank you,
Matteo
 
XmlSerializer works on public properties (not indexers); that is what
it does! You can customise by implementing IXmlSerializable; however,
another (simpler) approach may be to look into DataContractSerializer
(the new WCF serializer). This allows you to specify [DataMember] on
either properties or fields (public or private). The output is very
comparable.

Marc
 
Working example:

using System;
using System.Runtime.Serialization;
using System.Xml;
using System.Text;
using System.IO;
class Program {
static void Main() {
DataContractSerializer dcs = new
DataContractSerializer(typeof(Test));
Test test = new Test(new int[] { 30, 30, 30, 30 }, 200); // (I
change the array bounds just to check something)
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb)) {
dcs.WriteObject(writer, test);
}
string xml = sb.ToString();
using (XmlReader reader = XmlReader.Create(new
StringReader(xml))) {
Test test2 = (Test) dcs.ReadObject(reader);
}

}
}
[DataContract]
public class Test
{
[DataMember(Name="a")]
readonly int[] a; // same results with private
[DataMember]
readonly int b; // same results with private

public Test(int[] v1, int b)
{
a = v1;
this.b = b; // typo by OP
}

<SNIP>: the rest is "as was";
 
XmlSerializer works on public properties (not indexers); that is what
it does! You can customise by implementing IXmlSerializable; however,
another (simpler) approach may be to look into DataContractSerializer
(the new WCF serializer). This allows you to specify [DataMember] on
either properties or fields (public or private). The output is very
comparable.

Marc

Where is located DataContractSerializer class? Have I to dl from msdn?

But I fear the big problem is another: from the documentation it
appears DataContractSerializer it is not supported by Compact
framework, and the only reason I use XmlSerializer instead of binary
serialization is that compact framework supports only xml
serialization.
 
Yes, DataContractSerializer is available via MS download: search for
"WCF". But equally, no it doesn't appear to support CF (you didn't
mention you needed this ;-p). Assuming this is correct, then
IXmlSerializable remains an option (supported in CF 1.0 and 2.0);
shouldn't be too tricky...

Marc
 
Yes, DataContractSerializer is available via MS download: search for
"WCF". But equally, no it doesn't appear to support CF (you didn't
mention you needed this ;-p). Assuming this is correct, then
IXmlSerializable remains an option (supported in CF 1.0 and 2.0);
shouldn't be too tricky...

Marc

Sorry not having mentioned cf.
I think implementing IXmlSerializable takes off all the advantages of
using serialization. I use serialization to exchange a big class of
"parameters" between two application instead of using a customized
properties.txt file. If I have to customize the writing and reading of
a class based on the class structure then all the advantage is
gone ...
Thanks much anyway.

Matteo
 
One thing I've done before when working with XmlSerializer and complex
objects that don't interact with it well is store all of it's
"private" data in a separate class which is really public, kinda like
a memento. Then when I serialize my class I really just serialize the
memento and same with deserialize.

HTH,

Sam
 
Back
Top