Click here to Skip to main content
15,893,814 members
Articles / Programming Languages / C#

Class Library to Automatically Maintain Persistent Variables, Properties and Data Between Sessions

Rate me:
Please Sign up or sign in to vote.
4.50/5 (2 votes)
11 Jan 2008CPOL15 min read 44.1K   594   43  
A class library that maintains persistent variables, properties and data between sessions in XML files. It supports default values for new variables and events when the values in the XML file are changed
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.Runtime.InteropServices;

// Part of RJConfig V1.3

// Classes for the different value types for a ConfigVariable.

namespace RJConfig {
	// The built in config value type classes derived from CfgValueType<T>.

	//------------------------ Int type -----------------------------------------------------------------------------

	/// <remarks>
	/// The value class for a basic Int variable.
	/// </remarks>
	public class CfgValueTypeNum : CfgValueType<int> {
		/// <summary>
		/// Function to parse a string to the int value.
		/// </summary>
		/// <param name="str">The string to be parsed as an int.</param>
		public override void ParseString(string str)
		{
			try {
				mData = int.Parse(str);
			} catch {
				mData = 0;
			}
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The int value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals (int other)
		{
			return other == mData;
		}

		/// <summary>
		/// Function to make a string from the int value. The string must be able to be parsed back
		/// to an int with the ParseString function.
		/// </summary>
		/// <returns>The int value as a string.</returns>
		public override string MakeString()
		{
			return mData.ToString();
		}
	}

	/// <remarks>
	/// The CfgVarNum class is a config variable class for a numeric (int) variables. 
	/// The sole purpose of this class is to simplify varaible creation with new() in classes that 
	/// are going to use this config variable. This removes the need to type the generic type definition.
	/// Sort of a C++ typedef.
	/// </remarks>
	public class CfgVarNum : CfgVar<CfgValueTypeNum, int> {
		/// <summary>
		/// Public constructor. 
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		public CfgVarNum(Config c, string SectionName, string ItemName, string VariableName, int Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// ------------------------------ bool type ----------------------------------------------------------------------

	/// <remarks>
	/// The value class for a bool type variable.
	/// </remarks>
	public class CfgValueTypeBool : CfgValueType<bool> {
		/// <summary>
		/// Function to parse a string to the bool value.
		/// </summary>
		/// <param name="str">The string to be parsed as a bool.</param>
		public override void ParseString(string str)
		{
			mData = ((string.Compare(str, "1") == 0) || (string.Compare(str, "TRUE", true) == 0) || (string.Compare(str, "ON", true) == 0));
		}

		/// <summary>
		/// Function to make a string from the bool value. The string must be able to be parsed back
		/// to a bool with the ParseString function.
		/// </summary>
		/// <returns>The bool value as a string.</returns>
		public override string MakeString()
		{
			return string.Format("{0}", mData ? "true" : "false");
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The bool value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals (bool other)
		{
			return other == mData;
		}
	}

	/// <remarks>
	/// The Bool variable config class.
	/// <seealso cref="CfgVarNum"/>
	/// </remarks>
	public class CfgVarBool : CfgVar<CfgValueTypeBool, bool> {
		/// <summary>
		/// Public constructor for the bool variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		public CfgVarBool(Config c, string SectionName, string ItemName, string VariableName, bool Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// ------------------------------ string type --------------------------------------------------------------------
	
	/// <remarks>
	/// The value class for a string type variable.
	/// </remarks>
	public class CfgValueTypeString : CfgValueType<string>{
		/// <summary>
		/// Nothing needs to be parsed since the value is already a string.
		/// </summary>
		/// <param name="str">The string value.</param>
		public override void ParseString(string str)
		{
			mData = str;
		}

		/// <summary>
		/// Nothing needs to be parsed since the value is already a string.
		/// </summary>
		/// <returns>The string value</returns>
		public override string MakeString()
		{
			return mData;
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The string value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals (string other)
		{
			return other == mData;
		}
	}

	/// <remarks>
	/// The string variable config class.
	/// <seealso cref="CfgVarNum"/>
	/// </remarks>
	public class CfgVarString : CfgVar<CfgValueTypeString, string> {
		/// <summary>
		/// Public constructor for the string variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		public CfgVarString (Config c, string SectionName, string ItemName, string VariableName, string Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// ------------------------------- int with limits ---------------------------------------------------------------
	
	/// <remarks>
	/// The value type for an Int variable with lower and upper limits.
	/// </remarks>
	public class CfgValueTypeNumLimit : CfgValueType<int> {
		/// <summary>
		/// The internal member for the lower limit of this value
		/// </summary>
		protected int mLowerLimit=int.MinValue;
		/// <summary>
		/// The internal member for the upper limit of this value.
		/// </summary>
		protected int mUpperLimit=int.MaxValue;

		/// <summary>
		/// Public property for the lower limit of the int value.
		/// </summary>
		public int LowerLimit
		{
			get 
			{
				return mLowerLimit;
			}
			set	
			{
				mLowerLimit = value;
			}
		}

		/// <summary>
		/// Public property for the upper limit of the int value.
		/// </summary>
		public int UpperLimit
		{
			get
			{
				return mUpperLimit;
			}
			set	
			{
				mUpperLimit = value;
			}
		}

		/// <summary>
		/// Override for the Data property. The set function also verifies and limits 
		/// the value to be witin upper and lower limits.
		/// </summary>
		public override int Data
		{
			get
			{
				return mData;
			}
			set
			{
				mData = value;
				TrimData();
			}
		}

		/// <summary>
		/// Function that parses the string value to the int value. The limits of
		/// the value is also checked.
		/// </summary>
		/// <param name="str">The string representation of the int value.</param>
		public override void ParseString(string str)
		{
			try {
				mData = int.Parse(str);
			} catch {
				mData = 0;
			}
			TrimData();
		}

		/// <summary>
		/// Function to convert the int value to a string.
		/// </summary>
		/// <returns>The string value of the int.</returns>
		public override string MakeString()
		{
			return mData.ToString();
		}

		/// <summary>
		/// Function to make sure that the int value is within upper and lower limits.
		/// </summary>
		public void TrimData()
		{
			if (mData < mLowerLimit) mData = mLowerLimit;
			if (mData > mUpperLimit) mData = mUpperLimit;
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The int value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals (int other)
		{
			return other == mData;
		}
	}

	/// <remarks>
	/// The limited int value config class.
	/// </remarks>
	public class CfgVarNumLimit : CfgVar<CfgValueTypeNumLimit, int> {
		/// <summary>
		/// Public constructor for the limited int variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		/// <param name="LowerLimit">The minimum value for this variable.</param>
		/// <param name="UpperLimit">The maximum value for this variable.</param>
		public CfgVarNumLimit(Config c, string SectionName, string ItemName, string VariableName, int Def,int LowerLimit,int UpperLimit)
			:base(c,SectionName,ItemName,VariableName,Def)
		{
			cfgValueType.LowerLimit = LowerLimit;
			cfgValueType.UpperLimit = UpperLimit;
			cfgValueType.TrimData();		// Data has to be trimmed since upper and lower limits have changed.
		}
	}

	// ------------------------------------ Enum type ---------------------------------------------------------------
	
	/// <remarks>
	/// The value type for an enumerator variable.
	/// </remarks>
	public class CfgValueTypeEnum : CfgValueType<Enum>{
		/// <summary>
		/// The parse string function for the enumerator type.
		/// </summary>
		/// <param name="str">The enumerator type in string format.</param>
		public override void ParseString(string str)
		{
			int index=0;
			foreach (string s in Enum.GetNames(mData.GetType()))
			{
				if (string.Compare(str, s, true)==0)
				{
					mData =(Enum) Enum.GetValues(mData.GetType()).GetValue(index);
					return;
				}
				index++;
			}
			mData = (Enum)Enum.GetValues(mData.GetType()).GetValue(0);	//Default if no match is found.
																		// Perhaps better to have an exception here?
		}

		/// <summary>
		/// Function to convert the enum value to a string. 
		/// </summary>
		/// <returns>The converted enum value to string</returns>
		public override string MakeString()
		{
			return mData.ToString();
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The Enum value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals (Enum other)
		{
			return other == mData;
		}
	}

	/// <remarks>
	/// The enumerator value config class.
	/// </remarks>
	public class CfgVarEnum : CfgVar<CfgValueTypeEnum, Enum>{
		/// <summary>
		/// Public constructor for the XmlDocument type variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		public CfgVarEnum (Config c, string SectionName, string ItemName, string VariableName, Enum Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// ------------------------------------ Double type --------------------------------------------------------

	/// <remarks>
	/// The value type for an floating point Double variable.
	/// </remarks>
	public class CfgValueTypeDouble : CfgValueType<Double> {
		/// <summary>
		/// The parse string function for the Double type.
		/// </summary>
		/// <param name="str">The Double in string format.</param>
		public override void ParseString(string str)
		{
			mData = Double.Parse(str);
		}

		/// <summary>
		/// Function to convert the Double to a string. 
		/// </summary>
		/// <returns>The Double in string format.</returns>
		public override string MakeString()
		{
			return mData.ToString();
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The Double value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals(Double other)
		{
			return (mData == other);
		}
	}

	/// <remarks>
	/// The Double value type config class.
	/// </remarks>
	public class CfgVarDouble : CfgVar<CfgValueTypeDouble, Double> {
		/// <summary>
		/// Public constructor for the Double type variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if it the variable
		/// isn't found in the associated config file.</param>
		public CfgVarDouble(Config c, string SectionName, string ItemName, string VariableName, Double Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// ------------------------------------ XmlDocument type --------------------------------------------------------

	/// <remarks>
	/// The value type for an XmlDocument variable. The root node is the &lt;value&gt; element
	/// </remarks>
	public class CfgValueTypeXmlDoc : CfgValueType<XmlDocument> {
		/// <summary>
		/// The parse string function for XmlDocument type.
		/// </summary>
		/// <param name="str">The XmlDocument in string format inside the &lt;Value&gt; node. The &lt;Value&gt; level
		/// is handled by the Variable.</param>
		public override void ParseString(string str)
		{
			if (mData == null) {
				mData = new XmlDocument();
			}
			mData.LoadXml("<Value>"+str+"</Value>");
		}

		/// <summary>
		/// Function to convert the XmlDocument to a string. 
		/// </summary>
		/// <returns>The inner xml text below the &lt;Value&gt; root node</returns>
		public override string MakeString()
		{
			if (mData == null) {
				return "";
			} else {
				XmlNode valueNode = mData.SelectSingleNode("Value");
				if (valueNode != null) {
					return valueNode.InnerXml;
				} else {
					return "";
				}
			}
		}

		/// <summary>
		/// The equality function for the IEquateable interface
		/// </summary>
		/// <param name="other">The XmlDocument value to compare for equality with this value type.</param>
		/// <returns>true if other is equal to the type for this value.</returns>
		public override bool Equals(XmlDocument other)
		{
			if ((mData == null) && (other == null))
				return true;
			if ((mData == null) || (other == null))
				return false;
			return (mData.InnerText.CompareTo(other.InnerText)==0);
		}
	}

	/// <remarks>
	/// The XmlDocument type variable config class.
	/// </remarks>
	public class CfgVarXmlDoc : CfgVar<CfgValueTypeXmlDoc, XmlDocument> {
		/// <summary>
		/// Public constructor for the XmlDocument type variable config class.
		/// </summary>
		/// <param name="c">The Config object where this variable is going to be created.</param>
		/// <param name="SectionName">The section name for this variable.</param>
		/// <param name="ItemName">The item name for this variable.</param>
		/// <param name="VariableName">The name for this variable.</param>
		/// <param name="Def">The default value for this variable that will be used if the variable
		/// isn't found in the associated config file. Note that the Def is saved as a reference which means that
		/// the default value will change if the original object used as the default, is changed.
		/// A valid default XmlDocument can be null. If it has elements, the DocumentElement should be named "Value"</param>
		public CfgVarXmlDoc(Config c, string SectionName, string ItemName, string VariableName, XmlDocument Def)
			: base(c, SectionName, ItemName, VariableName, Def)
		{
		}
	}

	// =================================== Combined types ==============================================================

	// ----------------------------------- Dialog window position and visibility ---------------------------------------

	/// <remarks>
	/// Class that holds position and visible state for a modeless dialog form. Meant to live and be handled by the
	/// DlgPosSave class.
	/// <seealso cref="DlgPosSave"/>
	/// </remarks>
	public class CfgVarDlgWindowPos{
		/// <summary>
		/// Int type Config variable for the x-position of the dialog.
		/// </summary>
		public CfgVarNum xpos;
		/// <summary>
		/// Int type Config variable for the y-position of the dialog.
		/// </summary>
		public CfgVarNum ypos;
		/// <summary>
		/// Bool type Config variable for the visible state.
		/// </summary>
		public CfgVarBool visible;

		/// <summary>
		/// Public constructor.
		/// Creates xpos, ypos and visible variables and either loads them with saved values from the config file or
		/// initiates the config file and sets the variables to default values.
		/// The config file should normally be the variables file (Config.AppVarInst).
		/// </summary>
		/// <param name="c">The Config object for these variables. Normally the Config.AppVarInst (variables).</param>
		/// <param name="SectionName">Name of the Section where the dialog pos and state are to be kept. 
		/// This section can be used for other Items and variables for the modeless dialog. The Item for the
		/// variables are set to DialogWindowPos.</param>
		public CfgVarDlgWindowPos(Config c, string SectionName)
		{
			xpos = new CfgVarNum(c, SectionName, "DialogWindowPos", "XPos", 10);
			ypos = new CfgVarNum(c, SectionName, "DialogWindowPos", "YPos", 10);
			visible = new CfgVarBool(c, SectionName, "DialogWindowPos", "Visible", false); // Default is invisible.
		}

		/// <summary>
		/// Public constructor that also moves the dialog to the saved (or default) postion and sets the
		/// visible state.
		/// </summary>
		/// <param name="c">Config object for the variables.<seealso cref="CfgVarDlgWindowPos(Config,string)"/></param>
		/// <param name="SectionName">Section name for the variables.<seealso cref="CfgVarDlgWindowPos(Config,string)"/></param>
		/// <param name="f">The windows Forms class for the dialog.</param>
		public CfgVarDlgWindowPos(Config c,string SectionName,Form f)
			:this(c,SectionName)
		{
			GetCfg(f);
		}

		/// <summary>
		/// Sets the dialog position and state to the values saved in the config file.
		/// Normally called when the dialog is created.
		/// </summary>
		/// <param name="f">The windows Forms object for the dialog.</param>
		public void GetCfg(Form f)
		{
			f.StartPosition = FormStartPosition.Manual;
			f.Left = xpos.CfgData;
			f.Top = ypos.CfgData;
			f.Visible = visible.CfgData;
		}

		/// <summary>
		/// Sets the config variables values to the position and state of the Form. Normally called when 
		/// the dialog is destroyed.
		/// </summary>
		/// <param name="f">The windows Forms object for the dialog.</param>
		public void SetCfg(Form f)
		{
			xpos.CfgData = f.Left;
			ypos.CfgData = f.Top;
			visible.CfgData = f.Visible;
		}
	}

	// -------------------------------- Form window position, size and state ------------------------------------------

	/// <remarks>
	/// Class that holds position and state for a windows Forms form. Meant to live and be handled by the
	/// FormPosSave class.
	/// <seealso cref="FormPosSave"/>
	/// </remarks>
	public class CfgVarWindowPos {
		/// <summary>
		/// Structure needed for the GetWindowPlacement WIN32 API function
		/// </summary>
		internal struct WINDOWPLACEMENT
		{
			public int length;
			public int flags;
			public int showCmd;
			public POINT ptMinPosition;
			public POINT ptMaxPosition;
			public RECT rcNormalPosition;

			public struct RECT
			{
				public RECT(int l, int t, int r, int b)
				{
					Left = l;
					Top = t;
					Right = r;
					Bottom = b;
				}
				public int Left;
				public int Top;
				public int Right;
				public int Bottom;
			}

			public struct POINT
			{
				public POINT(int x, int y)
				{
					X = x;
					Y = y;
				}
				public int X;
				public int Y;
			}
		}

		// The Win32 API methods
		[DllImport("user32")]
		internal static extern int GetWindowPlacement(IntPtr hwnd, ref WINDOWPLACEMENT lpwndpl);
		/// <summary>
		/// The config variable for window x position.
		/// </summary>
		public CfgVarNum xpos;
		/// <summary>
		/// The config variable for window y position.
		/// </summary>
		public CfgVarNum ypos;
		/// <summary>
		/// The config variable for window width.
		/// </summary>
		public CfgVarNum width;
		/// <summary>
		/// The config variable for window height.
		/// </summary>
		public CfgVarNum height;
		/// <summary>
		/// The config variable for window state (maximized, normal, minimized).
		/// </summary>
		public CfgVarEnum state;

		/// <summary>
		/// Public constructor that initializes config variables.
		/// </summary>
		/// <param name="c">The Config object for these variables. Normally the Config.AppVarInst (variables).</param>
		/// <param name="SectionName">Name of the Section where the window form pos and state are to be kept. 
		/// This section can be used for other Items and variables for the form. The Item for the
		/// variables are set to WindowPos.</param>
		public CfgVarWindowPos(Config c, string SectionName)
		{
			xpos = new CfgVarNum(c, SectionName, "WindowPos", "XPos", 10);
			ypos = new CfgVarNum(c, SectionName, "WindowPos", "YPos", 10);
			width = new CfgVarNum(c, SectionName, "WindowPos", "Width", 200);
			height = new CfgVarNum(c, SectionName, "WindowPos", "Height", 200);
			state = new CfgVarEnum(c, SectionName, "WindowPos", "State", FormWindowState.Normal);
		}

		/// <summary>
		/// Public constructor that also moves the form to the saved (or default) postion and sets the
		/// window state.
		/// </summary>
		/// <param name="c">Config object for the variables.<seealso cref="CfgVarWindowPos(Config,string)"/></param>
		/// <param name="SectionName">Section name for the variables.<seealso cref="CfgVarWindowPos(Config,string)"/></param>
		/// <param name="f">The windows Forms object for the form.</param>
		public CfgVarWindowPos(Config c, string SectionName, Form f)
			:this(c, SectionName)
		{
			GetCfg(f);
		}

		/// <summary>
 		/// Sets the form position and state to the values saved in the config file. Normally called
		/// when the form is created.
		/// </summary>
		/// <param name="f">The windows Forms object for the form.</param>
		public void GetCfg(Form f)
		{
			f.StartPosition = FormStartPosition.Manual;
			f.Left = xpos.CfgData;
			f.Top = ypos.CfgData;
			f.Width = width.CfgData;
			f.Height = height.CfgData;
			f.WindowState = (FormWindowState)state.CfgData;
		}

		/// <summary>
		/// Saves the current form position and state to the config varables. Normally called just before the 
		/// form is destroyed.
		/// </summary>
		/// <param name="f"></param>
		public void SetCfg(Form f)
		{
			if (!f.IsDisposed) {
				state.CfgData = (f.WindowState == FormWindowState.Maximized) ? FormWindowState.Maximized : FormWindowState.Normal;
				WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
				GetWindowPlacement(f.Handle, ref wp);
				xpos.CfgData = wp.rcNormalPosition.Left;
				ypos.CfgData = wp.rcNormalPosition.Top;
				width.CfgData = wp.rcNormalPosition.Right - wp.rcNormalPosition.Left;
				height.CfgData = wp.rcNormalPosition.Bottom - wp.rcNormalPosition.Top;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Svep DesignCenter
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions