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

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
 
M

Marc Gravell

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
 
M

Marc Gravell

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";
 
B

Beorne

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.
 
M

Marc Gravell

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
 
B

Beorne

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
 
S

Samuel R. Neff

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top