You have some strange requirements - usually the list of objects is stored together, not in pieces. Here's what I got:
User class:
class User { public int Id { get; set; } public string Name { get; set; } public List<User> Friends { get; set; } = new List<User>(); }
Serialization list. Serialization goes in two streams (though file, though in storage). XDocument
used for serialization.
void SerializeUsers(List<User> userList, Stream baseStream, Stream connectionStream) { var doc1 = new XDocument( new XElement("allUsers", userList.Select(SerializeUserWithName))); doc1.Save(baseStream); var doc2 = new XDocument( new XElement("allUsers", userList.Select(SerializeUserWithFriendIds))); doc2.Save(connectionStream); } XElement SerializeUserWithName(User user) { return new XElement("user", new XAttribute("Id", user.Id), new XElement("Name", user.Name)); } XElement SerializeUserWithFriendIds(User user) { return new XElement("user", new XAttribute("Id", user.Id), new XElement("friends", user.Friends.Select(friend => new XElement("user", new XAttribute("Id", friend.Id))))); }
Now, deserialization. She is a little trickier, in two stages.
List<User> DeserializeUsers(Stream baseStream, Stream connectionStream) { var doc1 = XDocument.Load(baseStream); var allUsers = doc1.Element("allUsers") .Elements("user") .Select(DeserializeUserWithName) .ToList(); var doc2 = XDocument.Load(connectionStream); var userConnections = ExtractConnections(doc2.Element("allUsers").Elements("user")); var userById = allUsers.ToDictionary(user => user.Id); foreach (var user in allUsers) { var friendIds = userConnections[user.Id]; foreach (var friendId in friendIds) user.Friends.Add(userById[friendId]); } return allUsers; } Dictionary<int, List<int>> ExtractConnections(IEnumerable<XElement> users) { return users.ToDictionary( keySelector: user => (int)user.Attribute("Id"), elementSelector: user => user.Element("friends") .Elements("user") .Attributes("Id") .Select(id => (int)id) .ToList()); } User DeserializeUserWithName(XElement user) { return new User() { Id = (int)user.Attribute("Id"), Name = (string)user.Element("Name").Value }; }
And test code:
class Program { static void Main(string[] args) { new Program().Run(); } void Run() { var user1 = new User() { Id = 1, Name = "Natali" }; var user2 = new User() { Id = 2, Name = "Tom" }; var user3 = new User() { Id = 3, Name = "Stackoverflow" }; user1.Friends.Add(user2); user1.Friends.Add(user3); user2.Friends.Add(user1); user3.Friends.Add(user1); var allUsers = new List<User>() { user1, user2, user3 }; var s1 = new MemoryStream(); var s2 = new MemoryStream(); SerializeUsers(allUsers, s1, s2); s1.Position = 0; s2.Position = 0; var allUsers2 = DeserializeUsers(s1, s2); // списки allUsers и allUsers2 должны совпадать } }
Understand.
This kind of serialization (completely by hand) is quite fragile. Perhaps there is a more reliable or correct path with XML serialization through the attributes of classes (@Mstislav Pavlov understands this better).
Id
field in the class that represents the user, or does theId
exist only in the serialized version? - VladD