473,394 Members | 2,168 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

XmlSerializer and public ArrayList properties

Before I continue, I'm going to begin by saying I'm not by any means
an expert- I've been using .NET with C# for about 4 months now, and
basically just learning by example and docs.

A game project I work on uses Xml serialization to store game objects
for loading. One of the techniques we use is to make an array
property and use the set block to perform actions on the values after
they're loaded from the xml, as in:

public string[] Ids
{
set
{
foreach(string id in value) this.AddId(id);
}
get { return null}
}

Well, I had set about wanting some type independance and thought I
would use an ArrayList for a different such task. But when I set
about making a similar property of type ArrayList, I found that it
wasn't working at all. Set would get called, but the value was always
empty. (value.Count==0).

There IS a document on MSDN that describes the serialization of
ArrayLists. At first, therefore, I believed I was using the wrong
attributes and that the xml reader was ignoring what it thought was
unused elements.

http://msdn.microsoft.com/library/de...attributes.asp

While MSDN says that to serialize an ArrayList you should use the
[XmlElement] attribute, this is misleading in the document because it
creates a flat array- no <ArrayListName>(contents)</ArrayListName>,
just a sequence of named elements.

Instead, use the attributes that are also used for arrays.
[XmlArray("NameOfArrayElement")] and one or more
[XmlArrayItem("NameOfType", typeof(YourType)]. The document describes
these, and they work just fine for ArrayLists too.

I googled for MANY hours reading everything I could find on the
XmlSerializer and properties and arraylists-- so far I've not found
anywhere that lists what I found.

For Arrays, the XmlSerializer creates the array, fills it internally,
and then calls set() on the property with the filled array.

For ArrayLists, it uses a much more convoluted method:

1) The serializer calls get() to find out if the ArrayList is null or
not.

2) If and ONLY IF it is null, it then calls set() with a new, empty
ArrayList. This is the only time set() EVER MIGHT be called.

3) For every object deserialized from the xml, the serializer calls
get()- expecting a real, persisted arraylist to be returned- and uses
Add() on the result to add the object. If your get() returns a Clone
of the arraylist, it will never actually fill.

What does this mean? You CANNOT use a property to accept input from
an xml file without saving the result- the ArrayList MUST exist in a
field somewhere and MUST be returned by the get() property and setable
by the set() property.

Also, set() is NEVER called on the completely deserialized ArrayList-
only on empty new ones, if necessary. Therefore, you must use the
IDeserializationCallback interface and implement OnDeserialization()
to act on the contents of the filled arraylist after loading.
Having figured all this out, I THEN ran into a hurdle for one very
infrequently mentioned fact: IDeserializationCallback applies only to
the BinaryFormatter, NOT the XmlSerializer. Therefore, in your
applications loading method, you may find it to your advantage to
define your own IXmlDeserializationCallback interface and check for
it when an object is loaded.

The disadvantage to this method is that because the XmlSerializer is
not doing the actual calling, internal objects (fields, properties)
which implement this interface will NOT have the method invoked.
Therefore, in your implementation of OnXmlDeserialization(), you
should call ONXmlDeserialization for your fields that implement
IXmlDeserializationCallback.

I hope this helps somebody- this is my first post writing like I know
what I'm talking about! ;) I'll feel like quite the fool if everyone
already knew about this and I was the only one in the dark...)

--------------------------------
From: Jamus Sprinson
jamuspsi at earthlink dot net
Nov 12 '05 #1
1 4595
Thank you.

The behavior you have described for XML de-serializing ArrayLists makes
sense. think about the concepts - in general, whether you are talking about
xml de-serialization or not, the arraylist doesn't get destroyed and
re-created every time a caller adds an item to it; Instead, the usage
pattern for an arraylist is to create it (or set it, as you say), and then
add and remove items to it.

It is a typical design when exposing a property from a type to have a hidden
field that lies behind the property. The degernerate case is

public class Foo {
private ArrayList list;
public ArrayList List {
get { return list;}
set {list=value; }
}
}
"Jamus Sprinson" <ja******@earthlink.net> wrote in message
news:dc**************************@posting.google.c om...
Before I continue, I'm going to begin by saying I'm not by any means
an expert- I've been using .NET with C# for about 4 months now, and
basically just learning by example and docs.

A game project I work on uses Xml serialization to store game objects
for loading. One of the techniques we use is to make an array
property and use the set block to perform actions on the values after
they're loaded from the xml, as in:

public string[] Ids
{
set
{
foreach(string id in value) this.AddId(id);
}
get { return null}
}

Well, I had set about wanting some type independance and thought I
would use an ArrayList for a different such task. But when I set
about making a similar property of type ArrayList, I found that it
wasn't working at all. Set would get called, but the value was always
empty. (value.Count==0).

There IS a document on MSDN that describes the serialization of
ArrayLists. At first, therefore, I believed I was using the wrong
attributes and that the xml reader was ignoring what it thought was
unused elements.

http://msdn.microsoft.com/library/de...attributes.asp

While MSDN says that to serialize an ArrayList you should use the
[XmlElement] attribute, this is misleading in the document because it
creates a flat array- no <ArrayListName>(contents)</ArrayListName>,
just a sequence of named elements.

Instead, use the attributes that are also used for arrays.
[XmlArray("NameOfArrayElement")] and one or more
[XmlArrayItem("NameOfType", typeof(YourType)]. The document describes
these, and they work just fine for ArrayLists too.

I googled for MANY hours reading everything I could find on the
XmlSerializer and properties and arraylists-- so far I've not found
anywhere that lists what I found.

For Arrays, the XmlSerializer creates the array, fills it internally,
and then calls set() on the property with the filled array.

For ArrayLists, it uses a much more convoluted method:

1) The serializer calls get() to find out if the ArrayList is null or
not.

2) If and ONLY IF it is null, it then calls set() with a new, empty
ArrayList. This is the only time set() EVER MIGHT be called.

3) For every object deserialized from the xml, the serializer calls
get()- expecting a real, persisted arraylist to be returned- and uses
Add() on the result to add the object. If your get() returns a Clone
of the arraylist, it will never actually fill.

What does this mean? You CANNOT use a property to accept input from
an xml file without saving the result- the ArrayList MUST exist in a
field somewhere and MUST be returned by the get() property and setable
by the set() property.

Also, set() is NEVER called on the completely deserialized ArrayList-
only on empty new ones, if necessary. Therefore, you must use the
IDeserializationCallback interface and implement OnDeserialization()
to act on the contents of the filled arraylist after loading.
Having figured all this out, I THEN ran into a hurdle for one very
infrequently mentioned fact: IDeserializationCallback applies only to
the BinaryFormatter, NOT the XmlSerializer. Therefore, in your
applications loading method, you may find it to your advantage to
define your own IXmlDeserializationCallback interface and check for
it when an object is loaded.

The disadvantage to this method is that because the XmlSerializer is
not doing the actual calling, internal objects (fields, properties)
which implement this interface will NOT have the method invoked.
Therefore, in your implementation of OnXmlDeserialization(), you
should call ONXmlDeserialization for your fields that implement
IXmlDeserializationCallback.

I hope this helps somebody- this is my first post writing like I know
what I'm talking about! ;) I'll feel like quite the fool if everyone
already knew about this and I was the only one in the dark...)

--------------------------------
From: Jamus Sprinson
jamuspsi at earthlink dot net

Nov 12 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Stuart Robertson | last post by:
I am trying to find a solution that will allow me to use XmlSerializer to serialize/deserialize a collection of objects where a given object is shared between two or more other objects, and not...
0
by: Magne Ryholt | last post by:
Have a class with a public property named "TheFirstPropertyOfArrayListType" of type ArrayList, property has attribute XmlElement to describe the contents of the ArrayList, the contents is a public...
4
by: Andy Neilson | last post by:
I've run across a strange behaviour with XmlSerializer that I'm unable to explain. I came across this while trying to use XmlSerializer to deserialize from a the details of a SoapException. This...
16
by: Bob Rock | last post by:
Hello, when serializing an array of elements of a class Classname using XmlSerializer.Serialize() I get an XML like the following: <?xml version="1.0"> <ArrayOfClassname> ....... ..........
2
by: magister | last post by:
Hello I got this working but it is not how I really want it, basically I have an xml file which has a root of <test> and can be filled with 3 different types of <question> elements with different...
2
by: Kent Boogaart | last post by:
Hello all, I have two simple classes: Item and ItemCollection. Item stores a label for the item and an instance of ItemCollection for all child items. ItemCollection just stores a collection of...
5
by: Keith Bannister | last post by:
I'm new to .net so here goes. I'm tying to deserialize a class that is associated with an XML schema. I created the C# class with xsd.exe as below: xsd.exe /c /n:somenamespace...
4
by: Steve Long | last post by:
Hello, I hope this is the right group to post this to. I'm trying to serialize a class I've written and I'd like to be able to serialze to both binary and xml formats. Binary serialization is...
0
by: Chuck Bowling | last post by:
I'm not sure what I'm doing wrong here. I'm getting the exception "An unhandled exception of type 'System.InvalidOperationException' occurred in system.xml.dll Additional information: There...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.