using System;
using System.Xml;
using System.Collections;
using System.Reflection;
namespace Bitworking{
// SerializeContainer
// * 0..N
// |
// SerialXmlVar
// |
// V
// StringXmlVar -* IntXmlVar
// 1
public class SerialXmlVar {
protected string path_;
public SerialXmlVar(string path) {
path_ = path;
}
public virtual void Write(XmlNode root) {
}
public virtual void Read(XmlNode root) {
}
}
class StringSerialXmlVar : SerialXmlVar {
private string value_;
private string default_;
public StringSerialXmlVar(string path, string defaultValue) : base(path) {
value_ = defaultValue;
default_ = defaultValue;
}
public override void Write(XmlNode root) {
// Split up the path
XmlNode currentNode = root;
XmlDocument doc = root.OwnerDocument == null ? (XmlDocument)root : root.OwnerDocument;
string[] elementNames = path_.Split('/');
// traverse to the end of the path, creating nodes if need be
foreach (string name in elementNames) {
if ("" != name) {
XmlNode next = currentNode.SelectSingleNode(name);
if (null == next) {
next = doc.CreateElement(name);
currentNode.AppendChild(next);
}
currentNode = next;
}
}
// place the value as innerText() (do we need to check for encodings???!?!?)
currentNode.InnerText = value_;
}
public override void Read(XmlNode root) {
try {
XmlNode element = root.SelectSingleNode(path_);
value_ = (null == element) ? default_ : element.InnerText;
}
catch(Exception) {
value_ = default_;
}
}
public override string ToString() {
return value_;
}
public string Value {
set {
value_ = value;
}
get {
return value_;
}
}
}
class IntSerialXmlVar : SerialXmlVar {
private StringSerialXmlVar stringImpl_;
private int value_;
public IntSerialXmlVar(string path, int defaultValue) : base(path) {
stringImpl_ = new StringSerialXmlVar(path, defaultValue.ToString());
value_ = defaultValue;
}
public override void Write(XmlNode root) {
stringImpl_.Value = value_.ToString();
stringImpl_.Write(root);
}
public override void Read(XmlNode root) {
stringImpl_.Read(root);
value_ = int.Parse(stringImpl_.Value);
}
public int Value {
set {
value_ = value;
}
get {
return value_;
}
}
}
class BoolSerialXmlVar : SerialXmlVar {
private StringSerialXmlVar stringImpl_;
private bool value_;
public BoolSerialXmlVar(string path, bool defaultValue) : base(path) {
stringImpl_ = new StringSerialXmlVar(path, defaultValue.ToString());
value_ = defaultValue;
}
public override void Write(XmlNode root) {
stringImpl_.Value = value_.ToString().ToLower();
stringImpl_.Write(root);
}
public override void Read(XmlNode root) {
stringImpl_.Read(root);
value_ = stringImpl_.Value == "true" || stringImpl_.Value == "True";
}
public bool Value {
set {
value_ = value;
}
get {
return value_;
}
}
}
class SerializeContainer {
private ArrayList vars_;
public SerializeContainer() {
vars_ = new ArrayList();
}
public void Add(SerialXmlVar var) {
vars_.Add(var);
}
public void Write(string filename) {
XmlDocument doc = new XmlDocument();
doc.Load(filename);
foreach (SerialXmlVar var in vars_) {
var.Write(doc);
}
doc.Save(filename);
}
public void Read(string filename) {
XmlDocument doc = new XmlDocument();
doc.Load(filename);
foreach (SerialXmlVar var in vars_) {
var.Read(doc);
}
}
}
[AttributeUsage(AttributeTargets.Field)]
public class XmlStringSerialize : Attribute {
private string path_;
private string defaultValue_;
public XmlStringSerialize(string path, string defaultValue) {
path_ = path;
defaultValue_ = defaultValue;
}
public string DefaultValue {
get {
return defaultValue_;
}
}
public string Path {
get {
return path_;
}
}
}
[AttributeUsage(AttributeTargets.Field)]
public class XmlIntSerialize : Attribute {
private string path_;
private int defaultValue_;
public XmlIntSerialize(string path, int defaultValue) {
path_ = path;
defaultValue_ = defaultValue;
}
public int DefaultValue {
get {
return defaultValue_;
}
}
public string Path {
get {
return path_;
}
}
}
[AttributeUsage(AttributeTargets.Field)]
public class XmlBoolSerialize : Attribute {
private string path_;
private bool defaultValue_;
public XmlBoolSerialize(string path, bool defaultValue) {
path_ = path;
defaultValue_ = defaultValue;
}
public bool DefaultValue {
get {
return defaultValue_;
}
}
public string Path {
get {
return path_;
}
}
}
// This is a helper class that has two static functions, Read() and Write().
// Call Read() or Write() on an instance of a class that has been annotated with
// the above attributes (XmlIntSerialize, XmlStringSerialize) to read or write
// the attributes fields to an XML file. See the unit test cases for examples
// of how to use these custom attributes.
public class SerializeByAttributes {
private static SerialXmlVar WriteIfSerialized(object objectToSerialize, FieldInfo info) {
SerialXmlVar returnValue = null;
foreach (object attribute in info.GetCustomAttributes(true)) {
if (attribute is XmlStringSerialize) {
XmlStringSerialize attr = (XmlStringSerialize) attribute;
StringSerialXmlVar serializer = new StringSerialXmlVar(attr.Path, attr.DefaultValue);
serializer.Value = info.GetValue(objectToSerialize) as String;
returnValue = serializer;
}
if (attribute is XmlIntSerialize) {
XmlIntSerialize attr = (XmlIntSerialize) attribute;
IntSerialXmlVar serializer = new IntSerialXmlVar(attr.Path, attr.DefaultValue);
serializer.Value = (int) info.GetValue(objectToSerialize);
returnValue = serializer;
}
if (attribute is XmlBoolSerialize) {
XmlBoolSerialize attr = (XmlBoolSerialize) attribute;
BoolSerialXmlVar serializer = new BoolSerialXmlVar(attr.Path, attr.DefaultValue);
serializer.Value = (bool) info.GetValue(objectToSerialize);
returnValue = serializer;
}
}
return returnValue;
}
public static void Write(object objectToSerialize, string filename) {
SerializeContainer allVars = new SerializeContainer();
foreach (FieldInfo info in (objectToSerialize.GetType()).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) {
SerialXmlVar serializer = WriteIfSerialized(objectToSerialize, info);
if (null != serializer) {
allVars.Add(serializer);
}
}
allVars.Write(filename);
}
public static void Read(object objectToSerialize, string filename) {
SerializeContainer allVars = new SerializeContainer();
Hashtable mapFieldInfoToSerializer = new Hashtable();
foreach (FieldInfo info in (objectToSerialize.GetType()).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) {
SerialXmlVar serializer = WriteIfSerialized(objectToSerialize, info);
if (null != serializer) {
allVars.Add(serializer);
mapFieldInfoToSerializer.Add(info, serializer);
}
}
allVars.Read(filename);
foreach (FieldInfo info in mapFieldInfoToSerializer.Keys) {
if (mapFieldInfoToSerializer[info] is StringSerialXmlVar) {
StringSerialXmlVar ser = (StringSerialXmlVar) mapFieldInfoToSerializer[info];
info.SetValue(objectToSerialize, ser.Value);
} else if (mapFieldInfoToSerializer[info] is IntSerialXmlVar) {
IntSerialXmlVar ser = (IntSerialXmlVar) mapFieldInfoToSerializer[info];
info.SetValue(objectToSerialize, ser.Value);
} else if (mapFieldInfoToSerializer[info] is BoolSerialXmlVar) {
BoolSerialXmlVar ser = (BoolSerialXmlVar) mapFieldInfoToSerializer[info];
info.SetValue(objectToSerialize, ser.Value);
}
}
}
}
}
|