Let's say that I have a list of groups and a list of users. Inside groups is a list of users which belong to the group. I want these users to be references to individual users in the user list. So, I've got something like this...
public class User
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("cellphone")]
public string CellPhone { get; set; }
[XmlAttribute("email")]
public string Email { get; set; }
[XmlAttribute("id")]
public byte Id { get; set; }
}
public class Group
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("id")]
public byte Id { get; set; }
public List<User> GroupMember;
//????? LINK TO USER ?????
}
Now, let's say that I have the following XML...
<?xml version="1.0"?>
<libraries>
<library>
<users>
<user name="John" id="0" email="john@john.com" cellphone="555-111-1111"/>
<user name="Jason" id="1" email="jason@jason.com" cellphone="555-111-1112"/>
<user name="Jann" id="7" email="jann@jann.com" cellphone="555-111-1113"/>
</users>
<groups>
<group name="All" id="0">
<member id="0"/>
<member id="1"/>
<member id="7"/>
</group>
<group name="None" id="1">
</group>
</groups>
</library>
</libraries>
For now I've simply linked the two by using the id attributes of element member and element user. This seemed like an obvious field to link the two on but I am free to change it.
Regardless, what I want is to deserialize my XML into List<User> Users; and List<Group> Groups; and have the relationship automagically created. That is, the group members are referenced to users.
The only thing I can think of would be to create a GroupMember class and handle the get,set of the Id like so...
public class Group
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("id")]
public byte Id { get; set; }
public List<GroupMember> GroupMember;
}
public class GroupMember
{
User user;
[XmlAttribute("id")]
public byte Id
{
get
{
//Return user id
}
set
{
//Set reference to user in users list
}
}
}
... but this obviously won't work as GroupMember has no awareness of the users list.
Suggestions?

1 answers
Well, I don't think there's a way for the deserializer to do all this automatically but you can do it by writing a custom method of the Library class which you call just after deserialization.
This method will add a reference to the Library to each of its Groups so that the latter then have access to its Users list. You can then include a read only property in each Group to access the User information using the Ids as lookups.
Something like the following:
Notice that the XmlSerializer will ignore both the Library and GroupMembers properties of the Group class. The latter has no backing field and therefore generates the list of users each time it's read. This saves memory but may be slow if there are a large number of users for a given library.
Also, if you intend to add users to or remove users from particular groups post-deserialization and then serialize them back to disk, you should add/remove their Ids to/from the Members list as the changes will then synchronize automatically with the GroupMembers property.
answered 5 months ago by:
11603
499
Thanks! One question... I understand the use of the [XmlArray] and [XmlArrayItem] but don't understand how you get away with [XmlElement] on the list<Member>. Can you please explain that?
499
I think I can answer my own question here. I need to think of the xml modifiers (what's the proper name?) as describing the xml data and not the c sharp data structures. Although members is indeed a list (array of sorts), the modifier is describing the member tag as a simple element. If <member> was enclosed in a <members> tag then I would need to make use of the array and arrayitem modifiers. Correct?
499
Also, another silly question... each time the Groups.GroupMembers is accessed a new List<User> is created. When do these get cleaned up? Seems like if this was accessed quite often then there might be a bunch of List<User>'s hanging out there.
11603
Yes, you're correct about the <member> tags. Some of the attributes used in XML deserialization aren't particularly intuitive but as long as you remember that each xml tag needs to correspond either to the name of a C# entity or to the Name property of an attribute applied to that entity, then you can generally figure it out :)
11603
The List<User> objects will get cleaned up when there's no longer a reference to them. If you only ever access Group.GroupMembers through the same variable and don't pass the reference elsewhere, then each time the property is accessed the previous List<User> will become eligible for GC. If this worries you, then you could declare a private field of type List<User> in the Group class and assign a new empty List<User> object to that 'in situ' or in the constructor. The GroupMembers property could then reuse that object by clearing it and adding the Users to it each time it was accessed. The only drawbacks to doing this are that each Group object would then need an extra 4 bytes (or 8 bytes on x64) of heap memory for the additional field and, if you wanted to keep a snapshot of the membership at a particular point, then you'd need to clone the List before assigning it to another variable.