I created a configuration file App.config containing all the operating parameters relating to my application.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="MinConnectionCount" value="2"/>
<add key="MaxConnectionCount" value="7"/>
</appSettings>
</configuration>
In order to read these values and make them available to the entire application, just use the AppSettings property of the ConfigurationManager class as follows:
try
{
NameValueCollection myAppSettings = ConfigurationManager.AppSettings;
byte min = byte.Parse(myAppSettings["MinConnectionCount"]);
byte max = byte.Parse(myAppSettings["MaxConnectionCount"]);
}
catch (ConfigurationErrorsException e)
{
throw e;
}
The values read by the AppSettings property are of string type, so you must perform the necessary conversions and checks:
- You must make the appropriate conversions, ensuring that there is no parsing errors. It could be useful to verify that the values obtained by the conversion are consistent with the application domain: for example, the minimum number of connections must be less than the maximum number.
- Anything that involves loading the configuration must be done at application startup, because the loaded parameters could be used to allocate any data structures such as tables, queues, etc.. If they were to be encountered errors while loading the configuration, the application should use a default configuration: errors may be reported by an alert.
- Finally, the configuration must be read-only, meaning they should not be changed while the application runs. This also simplifies access by multiple threads.
In order to achieve these targets, I created a class that loads the configuration from the file and makes available, via the appropriate property, the converted parameters.
public class MyConfiguration
{
enum Errors
{
CONNECTION_RANGES_ERROR
// some other errors
}
private byte m_MinConnectionCount;
private byte m_MaxConnectionCount;
private readonly List<Errors> m_ConfigErrors = new List<Errors>();
public MyConfiguration()
{
try
{
NameValueCollection appSettings = ConfigurationManager.AppSettings;
if (!SetConnectionRanges(appSettings["MinConnectionCount"], appSettings["MaxConnectionCount"]))
m_ConfigErrors.Add(Errors.CONNECTION_RANGES_ERROR);
// ...
}
catch (ConfigurationErrorsException e)
{
throw e;
}
}
private bool SetConnectionRanges(string minCountStr, string maxCountStr)
{
if (byte.TryParse(minCountStr, out m_MinConnectionCount)
&& m_MinConnectionCount > 0
&& byte.TryParse(maxCountStr, out m_MaxConnectionCount)
&& m_MaxConnectionCount > m_MinConnectionCount)
return true;
m_MinConnectionCount = 2;
m_MaxConnectionCount = 7;
return false;
}
public byte MinConnectionCount { get { return m_MinConnectionCount; } }
public byte MaxConnectionCount { get { return m_MaxConnectionCount; } }
public List<Errors> GetErrors() { return m_ConfigErrors; }
}
The GetErrors() method allows to get a list of errors that occurred during the loading of configuration parameters: the user may be notified of these errors, and may be informed that the application has used the default values for parameters.
- How to make sure that this class is first instantiated during application startup?
- I could apply the singleton pattern to this class: in this way I should just invoke an
Instanceproperty as the first statement of theMainmethod. But where should I invoke theInstanceproperty in a WPF application? - Rather than using the singleton pattern, I could create a global variable for
MyConfigurationclass and invoke theGetErrors()method as first statement of theMainmethod. But where should I invoke theGetErrors()method in a WPF application?
Change your class to be
staticto ensure a single instance of it.Then you can invoke
MyConfiguration.GetErrors()in theLoadevent of the first form you show and report errors.