In application development, it is helpful to allow consumers
of the code to be able to configure the class through the configuration file or
some other means. However, you have to determine the scope of your
application. Do you really need to provide configuration? Do you really need
a lot of configurable settings if the application is an intranet web site with
a small user base?
The scope of the application really does matter, because any
application can usually be easily expanded to include configuration. Usually,
a custom application not exposing an API to the users doesn’t need much configuration
at all, a custom framework should have a lot of configurable settings, and
everything else should be somewhere in between.
For instance, developing a custom provider requires
configuration, as that is part of the setup you see with many of the built-in
providers in the .NET 2.0 framework. But data layer objects and most business
objects don't need much configuration at all, except maybe to expose a
connection string key for all of the data objects, and other similar
situations. For instance, for a class that uses security passwords, I created
a separate configuration element just for it, shown with a few of the
properties that I created.
Listing 12
public class PasswordsElement: ConfigurationElement
{
[ConfigurationProperty("minimumLength", DefaultValue = 6)]
public int MinimumLength
{
get
{
return (int)this["minimumLength"];
}
set
{
if (value < - 1)
throw new ArgumentOutOfRangeException("value");
this["minimumLength"] = value;
}
}
[ConfigurationProperty("minimumNumericCharacters", DefaultValue = 1)]
public int MinimumNumericCharacters
{
get
{
return (int)this["minimumNumericCharacters"];
}
set
{
if (value < - 1)
throw new ArgumentOutOfRangeException("value");
this["minimumNumericCharacters"] = value;
}
}
[ConfigurationProperty("minimumUpperCaseCharacters", DefaultValue = 1)]
public int MinimumUpperCaseCharacters
{
get
{
return (int)this["minimumUpperCaseCharacters"];
}
set
{
if (value < - 1)
throw new ArgumentOutOfRangeException("value");
this["minimumUpperCaseCharacters"] = value;
}
}
}
This security password management class requires a special
function, and therefore requires a specific way to configure it. However, for
most classes, whether they be a DAL object, a POCO object (Plain Old CLR
Object), a custom collection, etc. this would be overkill.
There are some handy custom configuration sections that can
aid in application development. For instance, having a global application
element with some basic features helps to centralize these settings throughout
the application. One such implementation is below:
Listing 13
public class ApplicationSection: ConfigurationSection
{
[ConfigurationProperty("defaultConnectionStringName", DefaultValue = "")]
public string DefaultConnectionStringName
{
get
{
return (string)this["defaultConnectionStringName"];
}
set
{
this["defaultConnectionStringName"] = value;
}
}
public static ApplicationSection Instance
{
get
{
return ConfigurationManager.GetSection("nucleo/application")as
ApplicationSection;
}
}
[ConfigurationProperty("isTesting", DefaultValue = false)]
public bool IsTesting
{
get
{
return (bool)this["isTesting"];
}
set
{
this["isTesting"] = value;
}
}
}
This element, in this instance, provides a default
connection string name, which can then be used in the data layer, in a custom
provider, or any other database-connected object. The IsTesting property is a
property I use to control whether the application is currently in unit testing,
which allows certain features I've built-in.