369 lines
16 KiB
C#
369 lines
16 KiB
C#
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(){}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents class that can serialize compatible marked properties.
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// XML element is expected to be something like <image>Image data Base64 encoded</image>
|
|
/// </summary>
|
|
/// <param name="xml">Image data</param>
|
|
/// <returns></returns>
|
|
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 <image> 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 <image> 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;
|
|
}
|
|
}
|
|
}
|