From 766f7bcf9d5e9b352af7933926ff9f3515cc76fd Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Wed, 23 Sep 2026 14:19:32 +0200 Subject: [PATCH] XML deserialization in C#: retarget net10.0, cache the serializer, read the XML files - Retarget both projects from net7.0 to net10.0. - Collapse MSTest.TestAdapter and MSTest.TestFramework 2.2.10 into MSTest 4.4.1; Microsoft.NET.Test.Sdk 18.10.1, coverlet.collector 10.0.1. - Program.cs moves to top-level statements. The Person and Library examples read person.xml and library.xml, which the project already copies to the output folder, so the sample runs the same code as the article. The record examples keep their raw strings. - Remove the stray BlobBuilder using directive and the duplicated one-line PersonRecord example (it also carried the only CS8602 warning of the retarget). - DeserializeXmlData moves into its own static class, XmlDeserializer; the four test call sites follow it. - Remove the unreachable private LibraryRecord(List) constructor. - Add PersonSerializer, a static readonly XmlSerializer built with an XmlRootAttribute, and a test for it. --- .../LibraryRecord.cs | 4 - .../PersonSerializer.cs | 16 ++ .../XMLDeserializationInCsharp/Program.cs | 147 +++++++----------- .../XMLDeserializationInCsharp.csproj | 2 +- .../XmlDeserializer.cs | 14 ++ .../XMLDeserializationTest.cs | 28 +++- .../XMLDeserializationTests.csproj | 9 +- 7 files changed, 117 insertions(+), 103 deletions(-) create mode 100644 xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/PersonSerializer.cs create mode 100644 xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XmlDeserializer.cs diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/LibraryRecord.cs b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/LibraryRecord.cs index 6513f509ed..62244d6461 100644 --- a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/LibraryRecord.cs +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/LibraryRecord.cs @@ -3,8 +3,4 @@ public record LibraryRecord() { public List Books { get; init; } = new(); - private LibraryRecord(List books) : this() - { - Books = books; - } } \ No newline at end of file diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/PersonSerializer.cs b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/PersonSerializer.cs new file mode 100644 index 0000000000..9c08067981 --- /dev/null +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/PersonSerializer.cs @@ -0,0 +1,16 @@ +using System.Xml.Serialization; + +namespace XMLDeserializationInCsharp; + +public static class PersonSerializer +{ + private static readonly XmlSerializer _serializer = + new(typeof(Person), new XmlRootAttribute("Contact")); + + public static Person? Deserialize(string xml) + { + using var reader = new StringReader(xml); + + return (Person?)_serializer.Deserialize(reader); + } +} diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/Program.cs b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/Program.cs index 50ee4f0823..53e01102c6 100644 --- a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/Program.cs +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/Program.cs @@ -1,96 +1,65 @@ -using System.Xml.Serialization; -using static System.Reflection.Metadata.BlobBuilder; +using System.Xml.Serialization; +using XMLDeserializationInCsharp; -namespace XMLDeserializationInCsharp -{ - public class Program - { - static void Main(string[] args) - { - var xmlData2 = """ John Doe 30 """; var person2 = DeserializeXmlData(xmlData2); Console.WriteLine($"Name: {person2.Name}, Age: {person2.Age}"); - - var xmlData = """ - - John Doe - 30 - - """; - - var person = DeserializeXmlData(xmlData); - if (person != null) - { - Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); - } - - var complexXML = """ - - - - Book 1 - Author 1 - - - Book 2 - Author 2 - - - - """; +var personSerializer = new XmlSerializer(typeof(Person)); - var library = DeserializeXmlData(complexXML); - if (library != null) - { - foreach (Book book in library.Books) - { - Console.WriteLine($"Title: {book.Title}, Author: {book.Author}"); - } - } +using (var reader = new StreamReader("person.xml")) +{ + var person = (Person?)personSerializer.Deserialize(reader); + if (person != null) + { + Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); + } +} - //Simple Deserialization - var personXML = """ - - John Wick - 35 - - """; - var personRecord = DeserializeXmlData(personXML); - if (personRecord != null) - { - Console.WriteLine($"Name: {personRecord.Name}, Age: {personRecord.Age}"); - } +var librarySerializer = new XmlSerializer(typeof(Library)); - //Complex Deserialization - var libraryXML = """ - - - - Book 3 - Author 3 - - - Book 4 - Author 4 - - - - """; +using (var reader = new StreamReader("library.xml")) +{ + var library = (Library?)librarySerializer.Deserialize(reader); + if (library != null) + { + foreach (Book book in library.Books) + { + Console.WriteLine($"Title: {book.Title}, Author: {book.Author}"); + } + } +} - var libraryRecord = DeserializeXmlData(libraryXML); - if (libraryRecord != null) - { - foreach (BookRecord book in libraryRecord.Books) - { - Console.WriteLine($"Title: {book.Title}, Author: {book.Author}"); - } - } - } +//Simple Deserialization +var personXML = """ + + John Wick + 35 + + """; +var personRecord = XmlDeserializer.DeserializeXmlData(personXML); +if (personRecord != null) +{ + Console.WriteLine($"Name: {personRecord.Name}, Age: {personRecord.Age}"); +} - public static T? DeserializeXmlData(string xmlData) - { - var serializer = new XmlSerializer(typeof(T)); - using var reader = new StringReader(xmlData); +//Complex Deserialization +var libraryXML = """ + + + + Book 3 + Author 3 + + + Book 4 + Author 4 + + + + """; - return (T?)serializer.Deserialize(reader); - } - } -} \ No newline at end of file +var libraryRecord = XmlDeserializer.DeserializeXmlData(libraryXML); +if (libraryRecord != null) +{ + foreach (BookRecord book in libraryRecord.Books) + { + Console.WriteLine($"Title: {book.Title}, Author: {book.Author}"); + } +} diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp.csproj b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp.csproj index 2886507093..caf174d97f 100644 --- a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp.csproj +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net10.0 enable enable diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XmlDeserializer.cs b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XmlDeserializer.cs new file mode 100644 index 0000000000..463d534e4e --- /dev/null +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationInCsharp/XmlDeserializer.cs @@ -0,0 +1,14 @@ +using System.Xml.Serialization; + +namespace XMLDeserializationInCsharp; + +public static class XmlDeserializer +{ + public static T? DeserializeXmlData(string xmlData) + { + var serializer = new XmlSerializer(typeof(T)); + using var reader = new StringReader(xmlData); + + return (T?)serializer.Deserialize(reader); + } +} diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTest.cs b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTest.cs index 67e5dca9f3..682a350163 100644 --- a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTest.cs +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTest.cs @@ -17,7 +17,7 @@ public void WhenDeserializingXmlData_ThenReturnExpectedPerson() """; var expectedPerson = new Person { Name = "Jane Smith", Age = 25 }; - var actualPerson = Program.DeserializeXmlData(xmlData); + var actualPerson = XmlDeserializer.DeserializeXmlData(xmlData); Assert.IsNotNull(actualPerson); Assert.AreEqual(expectedPerson.Name, actualPerson.Name); @@ -42,7 +42,7 @@ public void WhenDeserializingcomplexXML_ThenReturnBooks() """; - var library = Program.DeserializeXmlData(complexXML); + var library = XmlDeserializer.DeserializeXmlData(complexXML); Assert.IsNotNull(library); Assert.IsNotNull(library.Books); @@ -67,7 +67,7 @@ public void WhenDeserializingXmlData_ThenReturnPersonrecord() """; var expectedPerson = new PersonRecord { Name = "John Wick", Age = 35 }; - var actualPerson = Program.DeserializeXmlData(personXML); + var actualPerson = XmlDeserializer.DeserializeXmlData(personXML); Assert.IsNotNull(actualPerson); Assert.AreEqual(expectedPerson.Name, actualPerson.Name); @@ -93,7 +93,7 @@ public void WhenDeserializingXmlData_ThenReturnBooks() """; - var library = Program.DeserializeXmlData(libraryXML); + var library = XmlDeserializer.DeserializeXmlData(libraryXML); Assert.IsNotNull(library); Assert.IsNotNull(library.Books); @@ -105,5 +105,25 @@ public void WhenDeserializingXmlData_ThenReturnBooks() Assert.AreEqual("Keanu Reeves", library.Books[1].Title); Assert.AreEqual("BRZRKR", library.Books[1].Author); } + + [TestMethod] + public void WhenDeserializingWithCachedSerializer_ThenReturnPerson() + { + var contactXML = """ + + Jane Smith + 25 + + """; + + var first = PersonSerializer.Deserialize(contactXML); + var second = PersonSerializer.Deserialize(contactXML); + + Assert.IsNotNull(first); + Assert.AreEqual("Jane Smith", first.Name); + Assert.AreEqual(25, first.Age); + Assert.IsNotNull(second); + Assert.AreEqual(first.Name, second.Name); + } } } \ No newline at end of file diff --git a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTests.csproj b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTests.csproj index 54450687a4..5053957602 100644 --- a/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTests.csproj +++ b/xml-csharp/XMLDeserializationInCsharp/XMLDeserializationTests/XMLDeserializationTests.csproj @@ -1,7 +1,7 @@ - net7.0 + net10.0 enable enable @@ -10,10 +10,9 @@ - - - - + + +