Friday, 3 July 2009

AppConfig style xml based configuration in Windows Mobile

My first surprise when I start to learn Windows Mobile programming was the lack of Application configuration. So, I would like to show a solution to this problem.

First of all, you can create a new Windows mobile Class library. Then add a new xml file into library. Set the xml file Copy to Output Directory property Copy always.

Rename the Class1.cs for example Configuration.cs. Now you've got a class library with an empty xml file and a public class file which is also empty.

Next step to write the application configuration like xml file. Use configuration and appSettings tags, like appConfig. Look at my example below:

<?xml
version="1.0"
encoding="utf-8" ?>

<configuration>

<appSettings>


 

...


 

<add
key="url"
value="http://test.test:8080/example" />


 

...


 

</appSettings>

</configuration>


 

Next step to write the configuration class, which will be use the xml. Firs I use singleton pattern, to guarantee only one config of application.


public
class
Configuration

{

#region singleton


 


static
Configuration instance = null;


static
readonly
object padlock = new
object();


 

Configuration()

{

InitConfiguration();

}


 


public
static
Configuration Instance

{


get

{


lock (padlock)

{


if (instance == null)

{

instance = new
Configuration();

}


return instance;

}

}

}


 

#endregion


 

#region Constructor


///
<summary>


/// I use this init function to separate


/// singleton logic and constuctor logic


///
</summary>


private
void InitConfiguration()

{


 

}


 

#endregion

}


 

After this we need a NameValueCollection, which is hold setting into the memory. Some public property, which is good to read and write settings and a Load and Save method, which is load settings information from xml tom memory and save back, if we change something.

So these are the private fields, on for NameValuePair and one for the path of xml file:

#region private fields


 


private
NameValueCollection _settings;


private
string _settingsPath;


 

#endregion


 

These are the properties which are gets or sets information from the NameValuePair:

#region config fields


 


public
string ServerUri

{


get { return _settings.Get("url"); }


set { _settings.Set("url", value); }

}


 

#endregion


 

These are the operations which are creating date transfer between memory and xml file:

#region operators


 


///
<summary>


/// Gets settings fields from xml file


///
</summary>


public
static
void Load()

{


// Get the path of the settings file.

_settingsPath = Path.GetDirectoryName(

System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

_settingsPath += @"\Settings.xml";


 


if (!File.Exists(_settingsPath))


throw
new FileNotFoundException(

_settingsPath + " could not be found.");


 

System.Xml.XmlDocument xdoc = new XmlDocument();

xdoc.Load(_settingsPath);

XmlElement root = xdoc.DocumentElement;

System.Xml.XmlNodeList nodeList = root.ChildNodes.Item(0).ChildNodes;


 


// Add settings to the NameValueCollection.

_settings = new
NameValueCollection();

_settings.Add("url", nodeList.Item(4).Attributes["value"].Value);

}


 


///
<summary>


/// Save modified settings fields to xml file


///
</summary>


public
static
void Save()

{

XmlTextWriter tw = new XmlTextWriter(_settingsPath,

System.Text.UTF8Encoding.UTF8);

tw.WriteStartDocument();

tw.WriteStartElement("configuration");

tw.WriteStartElement("appSettings");


 


for (int i = 0; i < _settings.Count; ++i)

{

tw.WriteStartElement("add");

tw.WriteStartAttribute("key", string.Empty);

tw.WriteRaw(_settings.GetKey(i));

tw.WriteEndAttribute();


 

tw.WriteStartAttribute("value", string.Empty);

tw.WriteRaw(_settings.Get(i));

tw.WriteEndAttribute();

tw.WriteEndElement();

}


 

tw.WriteEndElement();

tw.WriteEndElement();


 

tw.Close();

}


 

#endregion


 

Don't forget, xml file is a string file, if you would like to hold another type value, for example integer, you always need type validation and explicit conversation.

It's more comfortable, if you call load method into the constructor, and call Save method into all of property setter:

#region Constructor


///
<summary>


/// I use this init function to separate


/// singleton logic and constuctor logic


///
</summary>


private
void InitConfiguration()

{

Load();

}


 

#endregion


 

#region config fields


 


public
string ServerUri

{


get { return _settings.Get("url"); }


set

{

_settings.Set("url", value);

Save();

}

}


 

#endregion


 

This solution is takes to me very comfortable to programming Windows Mobile. I hope you enjoy it, and it was useful to you!

This solution is not full of my work, some part of this solution I find on the net forums, and other blogs long time before.

No comments:

Post a Comment