XmlSerlializer is not serializing all properties of a class - c#

I wrote a generic method for Object to XML string using XMLSerializer class.
Below is my class
public class SampleJson
{
public string fname { get; set; }
public string lname { get; set; }
public int age { get; set; }
public AdditionalInformation AdditionalInformation { get; set; }
}
public class AdditionalInformation
{
public string firstlane { get; set; }
public string secondlane { get; set; }
public decimal? cityCode { get; set; }
public int? countryCode { get; set; }
public bool? isValid { get; set; }
public DateTime enteredDate { get; set; }
}
And below is Generic Method
public class QAZ
{
public static string Foo<T>(T dataToSerialize)
{
var stringWriter = new StringWriter();
XmlTextWriter xmlTextWriter = null;
var serializer = new XmlSerializer(dataToSerialize.GetType());
xmlTextWriter = new XmlTextWriter(stringWriter);
serializer.Serialize(xmlTextWriter, dataToSerialize);
return stringWriter.ToString();
}
}
class Bar
{
static void Main(string[] args)
{
var sampleJson = typeof(SampleJson);
var fooMethod = typeof(QAZ).GetMethod("Foo");
var fooOfBarMethod = fooMethod.MakeGenericMethod(new[] {sampleJson});
string xml= fooOfBarMethod.Invoke(new QAZ(), new object[] {new SampleJson()}).ToString();
Console.ReadKey();
}
}
But I'm getting the output is
<?xml version="1.0" encoding="UTF-16"?>
-<SampleJson xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<age>0</age>
</SampleJson>
I don't understand why XmlSerializer serializes only int property.
Can anyone please tell me the issue that I'm doing.
The main agenda here is I want to generate an xsd for SampleJson class. In order to do that I am trying to convert the class to xml. From xml to xsd. Is there a way to generate xsd from a class?

I think this might help you to understand better, I wrote an example please do like or dislike if it has or hasn't helped.
public class Vehicle
{
public string VRM;
}
class Program
{
static void Main(string[] args)
{
var Reg = new Vehicle { VRM = "LP65 UGT" };
var writer = new System.Xml.Serialization.XmlSerializer(typeof(Vehicle));
var wfile = new System.IO.StreamWriter(#"C:\Myexample\NewVehicle.xml");
writer.Serialize(wfile, Reg);
wfile.Close();
Console.WriteLine("Vehicle Reg is now written in xml format ");
Console.ReadKey();
}
}
The above example will write successfully to XML file ensure you create the folder first on your C drive My example and then run the above to see the result for yourself and see if it can point you to the correct direction hopefully.

Related

Serialize XmlAttribute which is an empty string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I got a class which represents a soccerplayer:
public class PlayerExtended
{
[XmlAttribute("id")] public string Id { get; set; }
[XmlAttribute("shortName")] public string ShortName { get; set; }
[XmlAttribute("firstName")] public string FirstName { get; set; }
[XmlAttribute("surName")] public string SurName { get; set; }
[XmlAttribute("shirtNumber")] public string ShirtNumber { get; set; }
[XmlAttribute("actions")] public string Actions { get; set; }
[XmlAttribute("substitude")] public string Substitude { get; set; }
[XmlAttribute("grade")] public string Grade { get; set; }
[XmlAttribute("iconSmall")] public string IconSmall { get; set; }
[XmlAttribute("position")] public string Position { get; set; }
[XmlAttribute("squadPositionID")] public string SquadPositionId { get; set; }
[XmlAttribute("squadPosition")] public string SquadPosition { get; set; }
[XmlAttribute("inMinute")] public string InMinute { get; set; }
[XmlAttribute("outMinute")] public string OutMinute { get; set; }
[XmlAttribute("captain")] public string Captain { get; set; }
}
After assigning values to the properties one of the players looks like this:
The property "Actions" is an empty string (NOT NULL).
If I serialize it it looks like this:
<player id="51641" shortName="Bürki" firstName="Roman" surName="Bürki" shirtNumber="1" substitude="starter" grade="2,5" iconSmall="xxx.whatever.com" position="11" squadPositionID="1" squadPosition="Torwart"/>
But I want it to look like this:
<player id="51641" shortName="Bürki" firstName="Roman" surName="Bürki" shirtNumber="1" actions="" substitude="starter" grade="2,5" iconSmall="xxx.whatever.com" position="11" squadPositionID="1" squadPosition="Torwart"/>
So how do I serialize an XmlAttribute which is an empty string?
How are you generating your XML? I cannot seem to reproduce your issue.
public class Program
{
public static void Main(string[] args)
{
using var writer = new StringWriter();
var serializer = new XmlSerializer(typeof(Player));
serializer.Serialize(writer, new Player { Name = "", Age = 25 });
Console.WriteLine(writer);
}
}
public class Player
{
[XmlAttribute("name")]
public string Name { get; set; }
[XmlAttribute("age")]
public int Age { get; set; }
}
The code above results in the name attribute in the format you desire (name=""). Let me know if this answer is sufficient for you.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
// Runtime Target = .NET Core v2.1 or .NET Core v3.1
namespace XmlSerialize
{
class Program
{
static void Main(string[] args)
{
var mickey = new Employee { FirstName = "Mickey", LastName = "Mouse" };
var asterix = new Employee { FirstName = "Asterix", LastName = "" };
var obelix = new Employee { FirstName = "Obelix", LastName = null };
var nixnix = new Employee { FirstName = null, LastName = null };
Console.WriteLine(SerializeXml(mickey) + SerializeXml(asterix) + SerializeXml(obelix) + SerializeXml(nixnix));
}
public static string SerializeXml<T>(T instanceToSerialize)
{
var serializer = new XmlSerializer(instanceToSerialize.GetType(), string.Empty);
var result = string.Empty;
using (var stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, instanceToSerialize);
result = stringWriter.ToString();
}
return result;
}
}
[XmlRoot("Employee")]
public sealed class Employee
{
[XmlAttribute("FirstName")]
public string FirstName { get; set; }
[XmlIgnore]
public string LastName { get; set; }
[XmlAttribute("LastName")]
public string SerializableLastName // <------------ Might this help?
{
get { return this.LastName ?? string.Empty; }
set { this.LastName = value; }
}
[XmlElement]
public List<string> Skills { get; set; }
}
}
Output
<?xml version="1.0" encoding="utf-16"?>
<Employee FirstName="Mickey" LastName="Mouse" />
<Employee FirstName="Asterix" LastName="" />
<Employee FirstName="Obelix" LastName="" />
<Employee LastName="" />
setting the property value to string.Empty will do the trick. I am using XmlSerializer to convert the object to XML. If I set the property to string.Empty, this will result as empty attribute in XML. Here is the example
public class TestClass
{
[XmlAttribute("test1")]
public string test1 { get; set; }
[XmlAttribute("test2")]
public string test2 { get; set; }
}
var dd = new List<TestClass>();
dd.Add( new TestClass() { test1 = "asdf", test2 = string.Empty }); //will generate empty attribute for test2
dd.Add( new TestClass() { test1 = "asdf" }); //the attribute test2 will be ignored
using (var stringwriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(dd.GetType());
serializer.Serialize(stringwriter, dd);
Console.WriteLine( stringwriter.ToString());
}
Output
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfTestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TestClass test1="asdf" test2="" />
<TestClass test1="asdf" />
</ArrayOfTestClass>

Deserialize portion of XmlDocument into object

I see this question often enough, but nobody's title really seems to depict their question. I get a large response object back from a Web API that contains general response information, along with the data object I want to deserialize.
Full XML:
<?xml version="1.0"?>
<root>
<status>
<apiErrorCode>0</apiErrorCode>
<apiErrorMessage/>
<dbErrorCode>0</dbErrorCode>
<dbErrorMessage/>
<dbErrorList/>
</status>
<data>
<modelName>ReportXDTO</modelName>
<modelData>
<id>1780</id>
<reportTitle>Access Level (select) with Door Assignment</reportTitle>
<hasParameters>true</hasParameters>
<parameters>
<dataType>STRING</dataType>
<title>Access Level:</title>
<index>1</index>
<allowMulti>true</allowMulti>
<selectSql>SELECT DISTINCT [Name] FROM dbo.[Levels] WHERE [PrecisionFlag] = '0' ORDER BY [Name] </selectSql>
<values>
<value>Door 1</value>
<used>1</used>
</values>
<values>
<value>Door 2</value>
<used>1</used>
</values>
<values>
<value>Door 3</value>
<used>1</used>
</values>
</parameters>
<sourceSql>SELECT [Name], [SData] FROM [Schedules]</sourceSql>
<report/>
</modelData>
<itemReturned>1</itemReturned>
<itemTotal>1</itemTotal>
</data>
<listInfo>
<pageIdRequested>1</pageIdRequested>
<pageIdCurrent>1</pageIdCurrent>
<pageIdFirst>1</pageIdFirst>
<pageIdPrev>1</pageIdPrev>
<pageIdNext>1</pageIdNext>
<pageIdLast>1</pageIdLast>
<itemRequested>1</itemRequested>
<itemReturned>1</itemReturned>
<itemStart>1</itemStart>
<itemEnd>1</itemEnd>
<itemTotal>1</itemTotal>
</listInfo>
</root>
I only want to deserialize the modelData element. The modelData object type is dynamic, depending on the API call.
I deserialize xml in other applications, and created the following method, but don't know how to specifically ONLY get the modelData element:
public static T ConvertXmltoClass<T>(HttpResponseMessage http, string elementName) where T : new()
{
var newClass = new T();
try
{
var doc = JsonConvert.DeserializeXmlNode(http.Content.ReadAsStringAsync().Result, "root");
XmlReader reader = new XmlNodeReader(doc);
reader.ReadToFollowing(elementName);
//The xml needs to show the proper object name
var xml = reader.ReadOuterXml().Replace(elementName, newClass.GetType().Name);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
var serializer = new XmlSerializer(typeof(T));
newClass = (T)serializer.Deserialize(stream);
}
}
catch (Exception e)
{
AppLog.LogException(System.Reflection.MethodBase.GetCurrentMethod().Name, e);
}
return newClass;
}
I have updated this thread multiple times now, to stay current. I started updating it with the first solution. But that solution by itself didn't solve the problem. With the code how it is right now, I get no exceptions, but don't get the xml deserialized to my object. Instead I get a new, blank object. Thoughts?
THOUGH the object type can change, here is my current object I am dealing with: (PLEASE NOTE, that I deserialize the exact xml in modelData, in the Web API)
namespace WebApiCommon.DataObjects
{
[Serializable]
public class ReportXDto
{
public ReportXDto()
{
Parameters = new List<ReportParameterXDto>();
}
public int Id { get; set; }
public string ReportTitle { get; set; }
public bool HasParameters { get; set; } = false;
public List<ReportParameterXDto> Parameters { get; set; }
public string SourceSql { get; set; }
public DataTable Report { get; set; }
}
[Serializable]
public class ReportXDto
{
public ReportXDto()
{
Parameters = new List<ReportParameterXDto>();
}
public int Id { get; set; }
public string ReportTitle { get; set; }
public bool HasParameters { get; set; } = false;
public List<ReportParameterXDto> Parameters { get; set; }
public string SourceSql { get; set; }
public DataTable Report { get; set; }
}
[Serializable]
public class ReportParameterValuesXDto
{
public string Value { get; set; } = "";
public bool Used { get; set; } = false;
}
}
Firstly, XmlSerializer is case sensitive. Thus your property names need to match the XML element names exactly -- unless overridden with an attribute that controls XML serialization such as [XmlElement(ElementName="id")]. To generate a data model with the correct casing I used http://xmltocsharp.azurewebsites.net/ which resulted in:
public class ReportParameterValuesXDto
{
[XmlElement(ElementName="value")]
public string Value { get; set; }
[XmlElement(ElementName="used")]
public string Used { get; set; }
}
public class ReportParametersXDto
{
[XmlElement(ElementName="dataType")]
public string DataType { get; set; }
[XmlElement(ElementName="title")]
public string Title { get; set; }
[XmlElement(ElementName="index")]
public string Index { get; set; }
[XmlElement(ElementName="allowMulti")]
public string AllowMulti { get; set; }
[XmlElement(ElementName="selectSql")]
public string SelectSql { get; set; }
[XmlElement(ElementName="values")]
public List<ReportParameterValuesXDto> Values { get; set; }
}
public class ReportXDto
{
[XmlElement(ElementName="id")]
public string Id { get; set; }
[XmlElement(ElementName="reportTitle")]
public string ReportTitle { get; set; }
[XmlElement(ElementName="hasParameters")]
public string HasParameters { get; set; }
[XmlElement(ElementName="parameters")]
public ReportParametersXDto Parameters { get; set; }
[XmlElement(ElementName="sourceSql")]
public string SourceSql { get; set; }
[XmlElement(ElementName="report")]
public string Report { get; set; }
}
(After generating the model, I modified the class names to match your naming convention.)
Given the correct data model, you can deserialize directly from a selected XmlNode using an XmlNodeReader as shown in How to deserialize a node in a large document using XmlSerializer without having to re-serialize to an intermediate XML string. The following extension method does the trick:
public static partial class XmlExtensions
{
public static IEnumerable<T> DeserializeElements<T>(this XmlNode root, string localName, string namespaceUri)
{
return new XmlNodeReader(root).DeserializeElements<T>(localName, namespaceUri);
}
public static IEnumerable<T> DeserializeElements<T>(this XmlReader reader, string localName, string namespaceUri)
{
var serializer = XmlSerializerFactory.Create(typeof(T), localName, namespaceUri);
while (!reader.EOF)
{
if (!(reader.NodeType == XmlNodeType.Element && reader.LocalName == localName && reader.NamespaceURI == namespaceUri))
reader.ReadToFollowing(localName, namespaceUri);
if (!reader.EOF)
{
yield return (T)serializer.Deserialize(reader);
// Note that the serializer will advance the reader past the end of the node
}
}
}
}
public static class XmlSerializerFactory
{
// To avoid a memory leak the serializer must be cached.
// https://stackoverflow.com/questions/23897145/memory-leak-using-streamreader-and-xmlserializer
// This factory taken from
// https://stackoverflow.com/questions/34128757/wrap-properties-with-cdata-section-xml-serialization-c-sharp/34138648#34138648
readonly static Dictionary<Tuple<Type, string, string>, XmlSerializer> cache;
readonly static object padlock;
static XmlSerializerFactory()
{
padlock = new object();
cache = new Dictionary<Tuple<Type, string, string>, XmlSerializer>();
}
public static XmlSerializer Create(Type serializedType, string rootName, string rootNamespace)
{
if (serializedType == null)
throw new ArgumentNullException();
if (rootName == null && rootNamespace == null)
return new XmlSerializer(serializedType);
lock (padlock)
{
XmlSerializer serializer;
var key = Tuple.Create(serializedType, rootName, rootNamespace);
if (!cache.TryGetValue(key, out serializer))
cache[key] = serializer = new XmlSerializer(serializedType, new XmlRootAttribute { ElementName = rootName, Namespace = rootNamespace });
return serializer;
}
}
}
Then you would deserialize as follows:
var modelData = doc.DeserializeElements<ReportXDto>("modelData", "").FirstOrDefault();
Working sample .Net fiddle here.
For Huge xml files always use XmlReader so you do not get an out of memory issue. See code below to get the element as a string :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
//or Create(Stream)
XmlReader reader = XmlReader.Create(FILENAME);
reader.ReadToFollowing("modelData");
if (!reader.EOF)
{
string modelDataStr = reader.ReadOuterXml();
}
}
}
}

How to get value inside XML tag?

I have the follow XML structure:
<Document>
<Sectors>
<Sector>
SectorName1
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector>
SectorName2
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Also I have classes for deserialize:
public class MetaDataXML
{
public class SectorXML
{
[XmlArrayItem(ElementName = "Sector")]
string SectorName { get; set; }
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
public List<SectorXML> Sectors { get; set; }
}
And part of code which do deserialize:
var xRoot = new XmlRootAttribute { ElementName = "Document", IsNullable = true };
var reader = new XmlSerializer(typeof(MetaDataXML), xRoot);
var data = (MetaDataXML)reader.Deserialize(streamXML);
After deserialization I successfully get subsectors velues, but I didn't get values for SectorName. How I need to organize my structure of class that I'll get values "SectorName1" and "SectorName2" for my string SectorName property?
I found that that this case it's a "Mixed Content". How we can parse this text values?
Whilst I am not entirely sure what it is you're trying to achieve here, I've made a few modifications to your XML class and provided some sample code below that is able to retrieve all of the information about a sector, including its name and the name of all the subsectors inside it.
XML Class:
namespace DocumentXml
{
[XmlRoot("Document")]
public class Document
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlAttribute("SectorName")]
public string SectorName { get; set; }
[XmlArray("Subsectors")]
[XmlArrayItem("Subsector")]
public string[] Subsectors { get; set; }
}
}
Main Program Class:
namespace DocumentXml
{
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
var serializer = new XmlSerializer(typeof(Document));
var document = serializer.Deserialize(File.OpenRead(path)) as Document;
var sectors = document.Sectors;
foreach (var s in sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
}
Sample XML:
<Document>
<Sectors>
<Sector SectorName="SectorName1">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
<Sector SectorName="SectorName2">
<Subsectors>
<Subsector>Subsector1</Subsector>
<Subsector>Subsector2</Subsector>
</Subsectors>
</Sector>
</Sectors>
</Document>
Output:
EDIT
Since the XML structure cannot be changed, this new class will preserve the structure and also allow you to get the value in question. XmlText returns everything inside the value so a custom set had to be used to ensure that the whitespace was correctly trimmed from it.
[XmlRoot("Document")]
public class MetaDataXml
{
[XmlArray("Sectors")]
[XmlArrayItem("Sector")]
public Sector[] Sectors { get; set; }
}
[XmlRoot("Sector")]
public class Sector
{
[XmlIgnore]
private string _sectorName;
[XmlText]
public string SectorName
{
get
{
return _sectorName;
}
set
{
_sectorName = value.Trim();
}
}
[XmlArray]
[XmlArrayItem(ElementName = "Subsector")]
public List<string> Subsectors { get; set; }
}
Sample Program:
class Program
{
static void Main(string[] args)
{
var path = #"D:\sandbox\DocumentXml\DocumentXml\Sample.xml";
using (var stream = File.OpenRead(path))
{
var deserializer = new XmlSerializer(typeof(MetaDataXml));
var data = (MetaDataXml)deserializer.Deserialize(stream);
foreach (var s in data.Sectors)
{
Console.WriteLine($"Sector Name: {s.SectorName}");
foreach (var ss in s.Subsectors)
{
Console.WriteLine($"Subsector Name: {ss}");
}
Console.WriteLine();
}
}
Console.ReadKey();
}
}

XML to custom Object

I have one xml file and I want to generate custom list from that xml using Linq.
here is my code. But I am not getting any records.Here is my code.
public class TemplateSettings {
public string DecimalSeparator { get; set; }
public string ThousandSeparator { get; set; }
public string DateSeparator { get; set; }
public string TimeSeparator { get; set; }
}
XML Here
<TemplateSetting>
<DecimalSeparator>1</DecimalSeparator>
<ThousandSeparator>2</ThousandSeparator>
<DateSeparator>3</DateSeparator>
<TimeSeparator>4</TimeSeparator>
<DateFormat>dd/MM/yyyy</DateFormat>
<ValueDelimiter>tr</ValueDelimiter>
<QuoteCharacter>r</QuoteCharacter>
<IsHeader>False</IsHeader>
</TemplateSetting>
And my code to get object from xml is
var a = (from x in objTemplateMasterEAL.TemplatSettingsXML.Elements("TemplateSetting")
select new TemplateSettings()
{
DateFormat = (string)x.Element("DateFormat"),
DecimalSeparator = (string)x.Element("DecimalSeparator"),
ThousandSeparator = (string)x.Element("ThousandSeparator"),
DateSeparator = (string)x.Element("DateSeparator"),
TimeSeparator = (string)x.Element("TimeSeparator"),
QuoteCharacter = (string)x.Element("QuoteCharacter"),
ValueDelimiter = (string)x.Element("ValueDelimiter"),
IsHeaderLine = (bool)x.Element("IsHeader")
}).ToList<TemplateSettings>();
Can any one suggest me what is wrong here ?
If your goal is just to deserialize the XML to object you can simply use this:
class Program
{
static void Main(string[] args)
{
using (StreamReader reader = new StreamReader("Sample.xml"))
{
var serializer = new XmlSerializer(typeof(TemplateSetting));
var templateSetting = (TemplateSetting)serializer.Deserialize(reader);
}
}
}
[XmlRoot]
public class TemplateSetting
{
public string DecimalSeparator { get; set; }
public string ThousandSeparator { get; set; }
public string DateSeparator { get; set; }
public string TimeSeparator { get; set; }
}
I make only on one change and its working fine for me.
<TemplateSettings>
<TemplateSetting>
<DecimalSeparator>1</DecimalSeparator>
<ThousandSeparator>2</ThousandSeparator>
<DateSeparator>3</DateSeparator>
<TimeSeparator>4</TimeSeparator>
<DateFormat>dd/MM/yyyy</DateFormat>
<ValueDelimiter>tr</ValueDelimiter>
<QuoteCharacter>r</QuoteCharacter>
<IsHeader>False</IsHeader>
</TemplateSetting>
</TemplateSettings>

Derived Class Deserialization

I have a problem with deserialization with my logic simulation program.
Here are my element classes:
public class AndGateData : TwoInputGateData
{
}
public class TwoInputGateData : GateData
{
public TwoInputGateData()
{
Input2 = new InputData();
Input1 = new InputData();
}
public InputData Input1 { get; set; }
public InputData Input2 { get; set; }
}
public class GateData : ElementData
{
public GateData()
{
OutputData = new OutputData();
}
public OutputData OutputData { get; set; }
}
public class ElementData
{
public int Delay { get; set; }
public Guid Id { get; set; }
}
And here are classes responsible for sockets:
public class InputData : SocketData
{
}
public class SocketData
{
public Guid Id { get; set; }
public SignalData SignalData { get; set; }
}
SignalData is not important here. So, I won't write it (in order to keep this question clean) here unless somebody says it is necessary.
CircuitData is very important:
[XmlRoot("Circuit")]
public class CircuitData
{
[XmlElement(typeof(AndGateData))]
[XmlElement(typeof(OrGateData))]
public List<ElementData> elements = new List<ElementData>();
public List<WireData> wires = new List<WireData>();
public void AddElement(ElementData element)
{
elements.Add(element);
}
public void AddWire(WireData wire)
{
wires.Add(wire);
}
}
Wires are not important right now.
Now, I have written some Serialization:
public class CircuitDataWriter
{
public static void Write(object obj, string fileName)
{
var xmlFormat = new XmlSerializer(typeof(CircuitData));
using(Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None) )
{
xmlFormat.Serialize(fStream,obj);
}
Console.WriteLine("Circuit saved in XML format.");
}
}
It works just like I wanted, it produces that xml document:
<?xml version="1.0"?>
-<Circuit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-<AndGateData>
<Delay>10</Delay>
<Id>bfee6dd7-5946-4b7b-9d0b-15d5cf60e2bf</Id>
-<OutputData> <Id>00000000-0000-0000-0000-000000000000</Id> </OutputData>
-<Input1> <Id>7c767caf-79a9-4c94-9e39-5c38ec946d1a</Id> <SignalData xsi:type="SignalDataOn"/> </Input1>
-<Input2> <Id>d2cad8f8-8528-4db3-9534-9baadb6a2a14</Id> <SignalData xsi:type="SignalDataOff"/> </Input2>
</AndGateData>
<wires/>
</Circuit>
But I have problem with my DESERIALIZATION. Here is the code:
public static CircuitData Read()
{
var reader = new XmlSerializer(typeof(CircuitData));
StreamReader file = new StreamReader("Circuit.xml");
var returnCircuitData = new CircuitData();
returnCircuitData = (CircuitData) reader.Deserialize(file);
return returnCircuitData;
}
Now, it deserializes my Circuit.xml to object, but this object only contains Id and Delay, it does not contain Input1, Input2 or Output. So, it is treated like Element, not like AndGate. I tried to solve it out for a day but it seems that no one has that kind of problem.
I have a suggestion for you, make the Write method generic like this and create the serializer using objectToSerialize.GetType():
public static void Write<T>(T objectToSerialize, string fileName)
{
var xmlSerializer = new XmlSerializer(objectToSerialize.GetType());
...
}
The XmlSerializer.Deserialize() method returns object, you can make your Read method generic like this:
public static T Read<T>(string fileName)
{
var serializer = new XmlSerializer(typeof(T));
using (StreamReader file = new StreamReader(fileName))
{
return (T)serializer.Deserialize(file);
}
}
Other than that you might want to read about:
XmlInclude that is used when you serialize derived classes.
XmlArray and XmlArrayItem that are used for controlling serialization of arrays

Categories

Resources