using System; using System.Text; using System.Xml; using System.Reflection; using System.Drawing; using System.ComponentModel; #if DOTNETBAR namespace DevComponents.DotNetBar #else namespace DevComponents.Tree #endif { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Field)] public class DevCoSerialize : Attribute { public DevCoSerialize(){} } /// /// Represents class that can serialize compatible marked properties. /// public class ElementSerializer { private static string XmlImageName="image"; private static string XmlIconName="icon"; private static string XmlAttributeName="name"; // private static string XmlCollectionName="collection"; // private static string XmlTypeName="type"; // private static string XmlObjectName="object"; public static void Serialize(object element, XmlElement xmlElem) { PropertyInfo[] propInfo = element.GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo prop in propInfo) { if (prop.GetCustomAttributes(typeof(DevCoSerialize), true).Length > 0) { // Check whether property needs to be serialized object[] attributesDefaultValue=prop.GetCustomAttributes(typeof(DefaultValueAttribute), true); if (attributesDefaultValue.Length > 0) { DefaultValueAttribute att=attributesDefaultValue[0] as DefaultValueAttribute; object propertyValue = prop.GetValue(element, null); if(propertyValue==att.Value) continue; if(propertyValue!=null && att.Value!=null && propertyValue.Equals(att.Value)) continue; } else if(element.GetType().GetMethod("ShouldSerialize" + prop.Name,BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)!=null) { MethodInfo mi=element.GetType().GetMethod("ShouldSerialize" + prop.Name,BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); object result=mi.Invoke(element,null); if(result is bool && !((bool)result)) continue; } string attributeName=XmlConvert.EncodeName(prop.Name); Type t=prop.PropertyType; if (t.IsPrimitive || t == typeof(string) || t.IsEnum) { if (t == typeof(string)) xmlElem.SetAttribute(attributeName, prop.GetValue(element, null).ToString()); else if (t.IsEnum) { xmlElem.SetAttribute(attributeName, Enum.Format(t, prop.GetValue(element, null), "g")); } else if (t == typeof(bool)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((bool)prop.GetValue(element, null))); else if (t == typeof(Int32)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((Int32)prop.GetValue(element, null))); else if (t == typeof(double)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((double)prop.GetValue(element, null))); else if (t == typeof(float)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((float)prop.GetValue(element, null))); else if (t == typeof(Int16)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((Int16)prop.GetValue(element, null))); else if (t == typeof(Int64)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((Int64)prop.GetValue(element, null))); else if (t == typeof(byte)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((byte)prop.GetValue(element, null))); else if (t == typeof(char)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((char)prop.GetValue(element, null))); else if (t == typeof(decimal)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((decimal)prop.GetValue(element, null))); else if (t == typeof(Guid)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((Guid)prop.GetValue(element, null))); else if (t == typeof(sbyte)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((sbyte)prop.GetValue(element, null))); else if (t == typeof(TimeSpan)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((TimeSpan)prop.GetValue(element, null))); else if (t == typeof(ushort)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((ushort)prop.GetValue(element, null))); else if (t == typeof(uint)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((uint)prop.GetValue(element, null))); else if (t == typeof(ulong)) xmlElem.SetAttribute(attributeName, XmlConvert.ToString((ulong)prop.GetValue(element, null))); else throw new ApplicationException("Unsupported serialization type '" + t.ToString() + "' on property '" + attributeName + "'"); } else if (t == typeof(Color)) xmlElem.SetAttribute(attributeName, ColorToString((Color)prop.GetValue(element, null))); else if (t == typeof(Image)) { XmlElement imageXmlElement = xmlElem.OwnerDocument.CreateElement(XmlImageName); imageXmlElement.SetAttribute(XmlAttributeName, attributeName); xmlElem.AppendChild(imageXmlElement); SerializeImage((Image)prop.GetValue(element, null), imageXmlElement); } else if (t == typeof(Icon)) { XmlElement imageXmlElement = xmlElem.OwnerDocument.CreateElement(XmlIconName); imageXmlElement.SetAttribute(XmlAttributeName, attributeName); xmlElem.AppendChild(imageXmlElement); SerializeIcon((Icon)prop.GetValue(element, null), imageXmlElement); } else if (t == typeof(Font)) { xmlElem.SetAttribute(attributeName, FontToString((Font)prop.GetValue(element, null))); } else throw new ApplicationException("Unsupported serialization type '" + t.ToString() + "'" + "' on property '" + attributeName + "'"); } } } private static string ColorToString(Color clr) { if (clr.IsSystemColor || clr.IsNamedColor || clr.IsKnownColor) return ("." + clr.Name); else return clr.ToArgb().ToString(); } private static Color ColorFromString(string sclr) { if (sclr == "") return Color.Empty; if (sclr[0] == '.') return Color.FromName(sclr.Substring(1)); else return Color.FromArgb(System.Xml.XmlConvert.ToInt32(sclr)); } private static string FontToString(Font font) { if (font == null) return ""; string s = font.Name + "," + XmlConvert.ToString(font.Size) + "," + XmlConvert.ToString(font.Bold) + "," + XmlConvert.ToString(font.Italic) + "," + XmlConvert.ToString(font.Underline) + "," + XmlConvert.ToString(font.Strikeout); return s; } private static Font FontFromString(string fontString) { if(fontString=="") return null; string[] options=fontString.Split(','); FontStyle fontStyle = FontStyle.Regular; if (XmlConvert.ToBoolean(options[2])) fontStyle |= FontStyle.Bold; if (XmlConvert.ToBoolean(options[3])) fontStyle |= FontStyle.Italic; if (XmlConvert.ToBoolean(options[4])) fontStyle |= FontStyle.Underline; if (XmlConvert.ToBoolean(options[5])) fontStyle |= FontStyle.Strikeout; Font font = new Font(options[0], XmlConvert.ToSingle(options[1]), fontStyle); return font; } public static void Deserialize(object element, XmlElement xmlElem) { Type type=element.GetType(); foreach(XmlAttribute att in xmlElem.Attributes) { string name=XmlConvert.DecodeName(att.Name); PropertyInfo prop=type.GetProperty(name); if(prop!=null) { Type t=prop.PropertyType; if (t.IsPrimitive) { if(t==typeof(bool)) prop.SetValue(element, XmlConvert.ToBoolean(att.Value), null); else if (t == typeof(Int32)) prop.SetValue(element, XmlConvert.ToInt32(att.Value), null); else if (t == typeof(double)) prop.SetValue(element, XmlConvert.ToDouble(att.Value), null); else if (t == typeof(float)) prop.SetValue(element, XmlConvert.ToSingle(att.Value), null); else if (t == typeof(Int16)) prop.SetValue(element, XmlConvert.ToInt16(att.Value), null); else if (t == typeof(Int64)) prop.SetValue(element, XmlConvert.ToInt64(att.Value), null); else if (t == typeof(byte)) prop.SetValue(element, XmlConvert.ToByte(att.Value), null); else if (t == typeof(char)) prop.SetValue(element, XmlConvert.ToChar(att.Value), null); else if (t == typeof(decimal)) prop.SetValue(element, XmlConvert.ToDecimal(att.Value), null); else if (t == typeof(Guid)) prop.SetValue(element, XmlConvert.ToGuid(att.Value), null); else if (t == typeof(sbyte)) prop.SetValue(element, XmlConvert.ToSByte(att.Value), null); else if (t == typeof(TimeSpan)) prop.SetValue(element, XmlConvert.ToTimeSpan(att.Value), null); else if (t == typeof(ushort)) prop.SetValue(element, XmlConvert.ToUInt16(att.Value), null); else if (t == typeof(uint)) prop.SetValue(element, XmlConvert.ToUInt32(att.Value), null); else if (t == typeof(ulong)) prop.SetValue(element, XmlConvert.ToUInt64(att.Value), null); } else if (t == typeof(string)) prop.SetValue(element, att.Value, null); else if (t.IsEnum) prop.SetValue(element, Enum.Parse(t, att.Value), null); else if (t == typeof(Color)) prop.SetValue(element, ColorFromString(att.Value), null); else if (t == typeof(Font)) prop.SetValue(element, FontFromString(att.Value), null); } } foreach(XmlElement childElem in xmlElem.ChildNodes) { if (childElem.Name == XmlImageName) { string name = XmlConvert.DecodeName(childElem.GetAttribute(XmlAttributeName)); PropertyInfo prop = type.GetProperty(name); if (prop != null) { prop.SetValue(element, DeserializeImage(childElem), null); } } else if (childElem.Name == XmlIconName) { string name = XmlConvert.DecodeName(childElem.GetAttribute(XmlAttributeName)); PropertyInfo prop = type.GetProperty(name); if (prop != null) { prop.SetValue(element, DeserializeIcon(childElem), null); } } } } public static void SerializeImage(System.Drawing.Image image,XmlElement xml) { if(image==null) return; System.IO.MemoryStream mem=new System.IO.MemoryStream(1024); // TODO: Beta 2 issue with the ImageFormat. RawFormat on image object does not return the actual image format // Right now it is hard coded to PNG but in final version we should get the original image format image.Save(mem,System.Drawing.Imaging.ImageFormat.Png); System.Text.StringBuilder sb=new System.Text.StringBuilder(); System.IO.StringWriter sw=new System.IO.StringWriter(sb); System.Xml.XmlTextWriter xt=new System.Xml.XmlTextWriter(sw); xt.WriteBase64(mem.GetBuffer(),0,(int)mem.Length); xml.InnerText=sb.ToString(); } public static void SerializeIcon(System.Drawing.Icon icon, XmlElement xml) { if(icon==null) return; System.IO.MemoryStream mem=new System.IO.MemoryStream(1024); // TODO: Beta 2 issue with the ImageFormat. RawFormat on image object does not return the actual image format // Right now it is hard coded to PNG but in final version we should get the original image format icon.Save(mem); System.Text.StringBuilder sb=new System.Text.StringBuilder(); System.IO.StringWriter sw=new System.IO.StringWriter(sb); System.Xml.XmlTextWriter xt=new System.Xml.XmlTextWriter(sw); xml.SetAttribute("encoding","binhex"); //xt.WriteBase64(mem.GetBuffer(),0,(int)mem.Length); xt.WriteBinHex(mem.GetBuffer(),0,(int)mem.Length); xml.InnerText=sb.ToString(); } /// /// XML element is expected to be something like Image data Base64 encoded /// /// Image data /// public static System.Drawing.Image DeserializeImage(XmlElement xml) { System.Drawing.Image img=null; if(xml==null || xml.InnerText=="") return null; System.IO.StringReader sr=new System.IO.StringReader(xml.OuterXml); System.Xml.XmlTextReader xr= new System.Xml.XmlTextReader(sr); System.IO.MemoryStream mem=new System.IO.MemoryStream(1024); // Skip to data xr.Read(); byte[] base64 = new byte[1024]; int base64len = 0; do { base64len = xr.ReadBase64(base64, 0, 1024); if(base64len>0) mem.Write(base64,0,base64len); } while (base64len!=0); img=System.Drawing.Image.FromStream(mem); return img; } public static System.Drawing.Icon DeserializeIcon(XmlElement xml) { System.Drawing.Icon img=null; if(xml==null || xml.InnerText=="") return null; bool bDecodeBinHex=false; if(xml.HasAttribute("encoding") && xml.GetAttribute("encoding")=="binhex") bDecodeBinHex=true; System.IO.StringReader sr=new System.IO.StringReader(xml.OuterXml); System.Xml.XmlTextReader xr= new System.Xml.XmlTextReader(sr); System.IO.MemoryStream mem=new System.IO.MemoryStream(1024); // Skip to data xr.Read(); byte[] base64 = new byte[1024]; int base64len = 0; if(bDecodeBinHex) { do { base64len = xr.ReadBinHex(base64, 0, 1024); if(base64len>0) mem.Write(base64,0,base64len); } while (base64len!=0); } else { do { base64len = xr.ReadBase64(base64, 0, 1024); if(base64len>0) mem.Write(base64,0,base64len); } while (base64len!=0); } mem.Position=0; img=new System.Drawing.Icon(mem); return img; } } }