Showing posts with label nokias. Show all posts
Showing posts with label nokias. Show all posts

Friday, April 7, 2017

Normandy Would be Nokias Android mobile

Normandy Would be Nokias Android mobile


This isnt really a rant about Windows Mobile per se, but its an issue I seem to run into on a consistent basis: you cant deserialize an XmlAttribute into a struct. Consider the following code:

using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Xml.Serialization; using System.IO; namespace SmartDeviceProject2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { XmlSerializer ser = new XmlSerializer(typeof(Foo)); string xml = "<Foo Moo="2,3"/>"; MemoryStream mem = new MemoryStream(); StreamWriter writer = new StreamWriter(mem); writer.Write(xml); writer.Flush(); mem.Seek(0, SeekOrigin.Begin); Foo f = (Foo)ser.Deserialize(mem); } } public struct Bar : IFormattable { public int X; public int Y; public static Bar Parse(string s) { string[] strings = s.Split(,); Bar ret = new Bar(); ret.X = int.Parse(strings[0]); ret.Y = int.Parse(strings[1]); return ret; } public override string ToString() { return string.Format("{0},{1}", X, Y); } #region IFormattable Members public string ToString(string format, IFormatProvider formatProvider) { return ToString(); } #endregion } public struct Foo { [XmlAttribute] public Bar Moo; } }

Attempting to run this code on the desktop would fail on the line that instantiates the XmlSerializer: "Cannot serialize member Moo of type SmartDeviceProject2.Foo. XmlAttribute/XmlText cannot be used to encode complex types.".

However, on .NET CF 2.0, it fails on deserialization with the cryptic message: "The type SmartDeviceProject2.Bar was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."

But my gripe is the following: I have a struct, it is IFormattable, and it can be Parsed (like int.Parse, DateTime.Parse, et al). Why is that not sufficient enough for serialization to and from an XmlAttribute string?

Anyways, here is the workaround:

  1. For all types that you want to be deserialized from attributes, explicitly give them the [XmlElement] attribute. Yes, you read that right.
  2. Create an XmlSerializer. Attach a new method to the UnknownAttribute event.
  3. Whenever this event is fired, use a combination of the attribute name and reflection to find the PropertyInfo/FieldInfo for what XmlSerializer cant deserialize. Then find that object types static Parse method, and call it on the attribute string. Then use that PropertyInfo/FieldInfo to set the property.

The new code would look something like this (you will need to add your own code to handle if it is a Property, since my sample is only looking for fields):

private void button1_Click(object sender, EventArgs e) { XmlSerializer ser = new XmlSerializer(typeof(Foo)); string xml = "<Foo Moo="2,3"/>"; MemoryStream mem = new MemoryStream(); StreamWriter writer = new StreamWriter(mem); writer.Write(xml); writer.Flush(); mem.Seek(0, SeekOrigin.Begin); ser.UnknownAttribute += new XmlAttributeEventHandler(ser_UnknownAttribute); Foo f = (Foo)ser.Deserialize(mem); } void ser_UnknownAttribute(object sender, XmlAttributeEventArgs e) { FieldInfo field = e.ObjectBeingDeserialized.GetType().GetField(e.Attr.Name); MethodInfo parse = field.FieldType.GetMethod("Parse"); field.SetValue(e.ObjectBeingDeserialized, parse.Invoke(null, new object[] { e.Attr.Value })); }
public struct Foo { [XmlElement] public Bar Moo; }

Unfortunately I have not figured out a similar workaround for serialization...


Go to link for download

Read more »