Yet Another IXmlSerializable questions... ahem...

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
I have read the numerous articles on the web about this subject but am unable to find an answer to my question, nor how to debug the generated .cs files as mentioned
<a title="here http://msdn.microsoft.com/en-us/library/aa302290.aspx" target="_blank
here .

I want to build equivalent xml as is produced when using the attributes [XmlAttribute] and [XmlElement] but with reflection based on a derived class of a class that implements IXmlSerializable and based on the complexity of the public Properties to be serialized
in the derived class. What does that mean? Well that If a class inherets my class the implements IXmlSerializable I will use reflection to find Properties to be serialized as attributes and elements. Arrays and Complex Types are serialized
as elements and strings and simple value types are serialized as attributes. Currently serialization fails to serialize correctly without any error and I havent implemented ReadXml fully/correctly before if I get feedback on what I am trying is possible.

I have tried to condense an example into the smallest amount of code possible, but it is still quite a bit. Consider the following:
//Implemented.cs

<div style="color:black; background-color:white
<pre><span style="color:blue using System.Linq;
<span style="color:blue using System.Text;
<span style="color:blue using System.Xml.Serialization;
<span style="color:blue using System.Xml;
<span style="color:blue using System.Reflection;
<span style="color:blue using System.ComponentModel;
<span style="color:blue using System.Collections;

<span style="color:blue namespace IXmlSerializableExample
{
<span style="color:blue public <span style="color:blue class Implemented : IXmlSerializable
{

<span style="color:blue public System.Xml.Schema.XmlSchema GetSchema() { <span style="color:blue return <span style="color:blue null; }

<span style="color:blue public <span style="color:blue void ReadXml(XmlReader reader)
{
reader.MoveToContent();

<span style="color:blue var attributes = GetAttributeProperties();
<span style="color:blue foreach (<span style="color:blue var attribute <span style="color:blue in attributes)
{
<span style="color:blue var value = reader.GetAttribute(attribute.Name);
<span style="color:blue var converter = TypeDescriptor.GetConverter(attribute.PropertyType);
<span style="color:blue var converted = converter.ConvertFromInvariantString(value);
attribute.SetValue(<span style="color:blue this, converted, <span style="color:blue null);
}

<span style="color:blue var elements = GetElementProperties();
<span style="color:blue var isEmpty = reader.IsEmptyElement;
reader.ReadStartElement();
<span style="color:blue if (!isEmpty)
{
<span style="color:green //not implemented; open to suggestions ;)

reader.ReadEndElement();
}
}

<span style="color:blue public <span style="color:blue void WriteXml(XmlWriter writer)
{
<span style="color:blue var attributes = GetAttributeProperties();
<span style="color:blue foreach (<span style="color:blue var attribute <span style="color:blue in attributes)
{
<span style="color:blue var value = attribute.GetValue(<span style="color:blue this, <span style="color:blue null);
<span style="color:blue if (value != <span style="color:blue null)
{
<span style="color:blue var converter = TypeDescriptor.GetConverter(value);
writer.WriteAttributeString(attribute.Name, converter.ConvertToInvariantString(value));
}
}

<span style="color:blue var elements = GetElementProperties();
<span style="color:blue foreach (<span style="color:blue var element <span style="color:blue in elements)
{
<span style="color:blue var value = element.GetValue(<span style="color:blue this, <span style="color:blue null);
<span style="color:blue if (value != <span style="color:blue null)
{
<span style="color:blue if (value <span style="color:blue is IEnumerable)
{
<span style="color:blue foreach (<span style="color:blue var item <span style="color:blue in value <span style="color:blue as IEnumerable)
{
<span style="color:blue if (item != <span style="color:blue null)
{
Type type = item.GetType();
<span style="color:blue if (type.IsValueType)
{
<span style="color:blue var converter = TypeDescriptor.GetConverter(item);
writer.WriteElementString(element.Name, converter.ConvertToInvariantString(item));
}
<span style="color:blue else
{
<span style="color:blue var serializer = <span style="color:blue new XmlSerializer(type);
serializer.Serialize(writer, item);
}
}
}
}
<span style="color:blue else
{
Type type = value.GetType();
<span style="color:blue var serializer = <span style="color:blue new XmlSerializer(type);
serializer.Serialize(writer, value);
}
}
}
}

<span style="color:blue private PropertyInfo[] GetAttributeProperties()
{
<span style="color:blue return (<span style="color:blue from property <span style="color:blue in <span style="color:blue this.GetType().GetProperties()
<span style="color:blue where property.PropertyType.Equals(<span style="color:blue typeof(<span style="color:blue string)) || property.PropertyType.IsValueType
<span style="color:blue where !IsTypeEnumerable(property.PropertyType)
<span style="color:blue select property).ToArray();
}
<span style="color:blue private PropertyInfo[] GetElementProperties()
{
<span style="color:blue return (<span style="color:blue from property <span style="color:blue in <span style="color:blue this.GetType().GetProperties()
<span style="color:blue where (!property.PropertyType.Equals(<span style="color:blue typeof(<span style="color:blue string)) && property.PropertyType.IsClass) || IsTypeEnumerable(property.PropertyType)
<span style="color:blue select property).ToArray();
}
<span style="color:blue private <span style="color:blue bool IsTypeEnumerable(Type type)
{
<span style="color:blue return type.GetInterfaces().Any(i => i.Equals(<span style="color:blue typeof(IEnumerable<>)));
}
}
}
[/code]


<br/>
//ImplementedDerived.cs

<div style="color:black; background-color:white
<pre><span style="color:blue using System;
<span style="color:blue using System.Collections.Generic;
<span style="color:blue using System.Linq;
<span style="color:blue using System.Text;
<span style="color:blue using System.Xml.Serialization;

<span style="color:blue namespace IXmlSerializableExample
{
<span style="color:blue public <span style="color:blue class ImplementedDerived : Implemented
{
<span style="color:blue public <span style="color:blue string Name { <span style="color:blue get; <span style="color:blue set; }
<span style="color:blue public <span style="color:blue int Age { <span style="color:blue get; <span style="color:blue set; }
<span style="color:blue public <span style="color:blue int[] FavNums { <span style="color:blue get; <span style="color:blue set; }
<span style="color:blue public NotDerivedNested Nested { <span style="color:blue get; <span style="color:blue set; }
}
}

[/code]

<br/>
<br/>

//NotDerived.cs

<div style="color:black; background-color:white
<pre><span style="color:blue using System;
<span style="color:blue using System.Collections.Generic;
<span style="color:blue using System.Linq;
<span style="color:blue using System.Text;
<span style="color:blue using System.Xml.Serialization;

<span style="color:blue namespace IXmlSerializableExample
{
<span style="color:blue public <span style="color:blue class NotDerived
{
[XmlAttribute]
<span style="color:blue public <span style="color:blue string Name { <span style="color:blue get; <span style="color:blue set; }

[XmlAttribute]
<span style="color:blue public <span style="color:blue int Age { <span style="color:blue get; <span style="color:blue set; }

[XmlElement]
<span style="color:blue public <span style="color:blue int[] FavNums { <span style="color:blue get; <span style="color:blue set; }

[XmlElement]
<span style="color:blue public NotDerivedNested Nested { <span style="color:blue get; <span style="color:blue set; }
}
}
[/code]

<br/>
<br/>

//NotDerivedNested.cs

<div style="color:black; background-color:white
<pre><span style="color:blue using System;
<span style="color:blue using System.Collections.Generic;
<span style="color:blue using System.Linq;
<span style="color:blue using System.Text;
<span style="color:blue using System.Xml.Serialization;

<span style="color:blue namespace IXmlSerializableExample
{
<span style="color:blue public <span style="color:blue class NotDerivedNested
{
[XmlAttribute]
<span style="color:blue public <span style="color:blue string Name { <span style="color:blue get; <span style="color:blue set; }

[XmlAttribute]
<span style="color:blue public <span style="color:blue int Age { <span style="color:blue get; <span style="color:blue set; }

[XmlElement]
<span style="color:blue public <span style="color:blue int[] FavNums { <span style="color:blue get; <span style="color:blue set; }
}
}

[/code]

<br/>
<br/>

//Programs.cs

<div style="color:black; background-color:white
<pre><span style="color:blue using System;
<span style="color:blue using System.Collections.Generic;
<span style="color:blue using System.Linq;
<span style="color:blue using System.Text;
<span style="color:blue using System.Xml.Serialization;
<span style="color:blue using System.IO;

<span style="color:blue namespace IXmlSerializableExample
{
<span style="color:blue class Program
{
<span style="color:blue public <span style="color:blue const <span style="color:blue string ImplementedDerived = <span style="color:#a31515 "ImplementedDerived.xml";
<span style="color:blue public <span style="color:blue const <span style="color:blue string NotDerived = <span style="color:#a31515 "NotDerived.xml";
<span style="color:blue static <span style="color:blue void Main(<span style="color:blue string[] args)
{
<span style="color:blue var nested = <span style="color:blue new NotDerivedNested
{
Name = <span style="color:#a31515 "NotDerivedNested",
Age = 1,
FavNums = <span style="color:blue new <span style="color:blue int[] { 1, 2 }
};

NotDerived nd = <span style="color:blue new NotDerived
{
Name = <span style="color:#a31515 "NotDerived",
Age = 7,
FavNums = <span style="color:blue new <span style="color:blue int[] { 13, 37 },
Nested = nested
};

ImplementedDerived id = <span style="color:blue new ImplementedDerived
{
Name = <span style="color:#a31515 <span style="color:#a31515 "<span style="color:#000000 ImplementedDerived<span style="color:#a31515 ",<br/> Age = 7,
FavNums = <span style="color:blue new <span style="color:blue int[] { 13, 37 },
Nested = nested
};

<span style="color:blue try
{
<span style="color:blue var serializer = <span style="color:blue new XmlSerializer(<span style="color:blue typeof(NotDerived));
<span style="color:blue using (<span style="color:blue var sw = <span style="color:blue new StreamWriter(NotDerived))
{
serializer.Serialize(sw, nd);
}

<span style="color:blue using (<span style="color:blue var sr = <span style="color:blue new StreamReader(NotDerived))
{
nd = (NotDerived)serializer.Deserialize(sr);
}

serializer = <span style="color:blue new XmlSerializer(<span style="color:blue typeof(ImplementedDerived));
<span style="color:blue using (<span style="color:blue var sw = <span style="color:blue new StreamWriter(ImplementedDerived))
{
serializer.Serialize(sw, id);
}

<span style="color:blue using (<span style="color:blue var sr = <span style="color:blue new StreamReader(ImplementedDerived))
{
id = (ImplementedDerived)serializer.Deserialize(sr); <span style="color:green // <-- will error because ReadXml is not implemented correctly yet
}
}
<span style="color:blue catch (Exception ex)
{
Console.WriteLine(ex.Message);
}

}
}
}

[/code]

<br/>
<br/>

<br/>
<br/>

View the full article
 
Back
Top