Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Adding Configuration File Support in Windows Mobile 6.x

4.75/5 (5 votes)
11 Aug 2016CPOL2 min read 6.9K  
Learn how to add support for .config files in .NET CF.

Introduction

The Compact Framework does not include native support for a .config file.  This article will explain how simple it is to build that support back into your application.

Creating the app.config

What you first need is an app.config file in your Project.  Since .config is not available for adding new items to your Project select anything (.cs is fine) and name it app.config.  Your new app.config file will have the default namespace/class junk in it.  Delete all that and create your .config.  This sample one looks like this:

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

    <add key="Username" value="user"/>
    <add key="Password" value="pass"/>
    <add key="Port" value="1234"/>
    
  </appSettings>
</configuration>

While .NET CF doesn't contain any libraries to read a .config at least when you compile your application the app.config is renamed correctly:

before you use your application you will need to copy/paste this renamed .config into your application directory or make sure its included in your .CAB Setup Project.

Using the code

The included ConfigurationManager class in the CompactFrameworkSupplements.dll can be referenced and used in any Windows Mobile 6 application with just a few lines of code:

C#
private void LoadAppSettings()
{
    string error = string.Empty;
    var cm = new ConfigurationManager();
    if (cm.ValidateAppSettings(out error, new AppSettings()))
    {
        _appSettings = new AppSettings();
        cm.LoadAppSettings(_appSettings);
        textBox1.Text = "AppSettings loaded!";
    }
    else
        textBox1.Text = error;
}

 

the _appSettings object is now loaded with all the values from your .config file.  When its time to extend your application and you need additional information from the .config file.  Simply add a key/value pair to the .config and a matching Property to your AppSettings class.  That's it!

 

Lets see how the magic happens:

ValidateAppSettings passes any errors out and takes an instance of your class that will be used in your application to hold the contents of the app.config.  In this example my class is called AppSettings and looks like this:

C#
public class AppSettings
{
    [Required(true)]
    public string Username { get; set; }
    [Required(true)]
    public string Password { get; set; }
    public int Port { get; set; }
}

ValidateAppSettings has 3 main purposes in life:

  1. Does the .config contain a Key for every Property defined in the AppSettings class? 
  2. Do all the marked Required properties in the AppSettings class have values in the .config?
  3. Do the values match the expected data types of the properties in AppSettings?

 

and it looks like this:

C#
        public bool ValidateAppSettings(out string error, object classInstanceToReadAppSettingNamesAndTypesFrom)
        {
            error = string.Empty;

            var expectedSettings = new Dictionary<string, Type>();
            var attrDictionary = new Dictionary<string, object[]>();

            var pis = classInstanceToReadAppSettingNamesAndTypesFrom.GetType().GetProperties();
            foreach (var pi in pis)
            {
                expectedSettings.Add(pi.Name, pi.PropertyType);
                attrDictionary.Add(pi.Name, pi.GetCustomAttributes(false));
            }

            foreach (var expectedSetting in expectedSettings)
            {
                var invalidValueError = "Config contains an invalid value for " + expectedSetting.Key;

                if (!AppSettings.ContainsKey(expectedSetting.Key))
                {
                    error = "Config does not contain " + expectedSetting.Key;
                    return false;
                }
                bool isRequired = IsConfigSettingRequired(attrDictionary, expectedSetting);

                switch (expectedSetting.Value.FullName)
                {
                    case "System.String":
                        if (isRequired && String.IsNullOrEmpty(AppSettings[expectedSetting.Key]))
                            error = invalidValueError;
                        break;
                    case "System.Int32":
                        if (isRequired && !AppSettings[expectedSetting.Key].IsInt32())
                            error = invalidValueError;
                        break;
                    case "System.Int64":
                        if (isRequired && !AppSettings[expectedSetting.Key].IsInt64())
                            error = invalidValueError;
                        break;
                    case "System.Double":
                        if (isRequired && !AppSettings[expectedSetting.Key].IsDouble())
                            error = invalidValueError;
                        break;
                    case "System.Boolean":
                        if (isRequired && !AppSettings[expectedSetting.Key].IsBoolean())
                            error = invalidValueError;
                        break;
                    case "System.DateTime":
                        if (isRequired && !AppSettings[expectedSetting.Key].IsDateTime())
                            error = invalidValueError;
                        break;

                }
            }

            return error == string.Empty;
        }

 

LoadAppSettings takes the instance of your AppSettings class that will be used in your application and uses reflection to set the values of the Properties:

C#
        public void LoadAppSettings(object classInstanceToLoadAppSettingsInto)
        {
            try
            {
                var pis = classInstanceToLoadAppSettingsInto.GetType().GetProperties();
                foreach (var pi in pis)
                {
                    if (String.IsNullOrEmpty(AppSettings[pi.Name])) continue;
                    pi.SetValue(classInstanceToLoadAppSettingsInto, Convert.ChangeType(AppSettings[pi.Name], pi.PropertyType, null), null);
                }
            }
            catch (Exception)
            {
                throw new InvalidOperationException("Failed to load App Settings.  Verify .config and class properties.");
            }
        }

Points of Interest

Reflection is amazing and super powerful even in the handycapped .NET 2.0 compact framework.

History

 

License

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