If you’re one of those dev’s that slaps a ConfigurationManager.AppSettings in the middle of a class then stop, please just stop. I know that it works but the side effect is that you’re creating a hidden dependency that dev’s who come along afterwards to maintain the code know nothing about and then get bitten in the ass when they try to change something (yes I know you should look through the code for things like this but I was in a hurry ok?)
To be clear, I believe that settings should be injected into classes that need them rather than having to provide a whole object to handle it (think of a connection string) but if you're refactoring old code and already have the dependency then its good to be able to start off by being able to see the dependency rather than have it hidden.
I know what you’re going to say “but its a static class so I don’t have any other way to use it”, but that’s where you’re wrong and with a little work you can have dependency injected, unit tested code loveliness and in fact I’ve done the work for you all you have to do is reuse it!
So what’ve I done? Well quite simply just written a wrapper around the ConfigurationManager’s static methods that allow you to use it via an interface and inject it into any classes that may need it, lets look at some code to see it a little clearer.
Here we have an absurdly simple example that demonstrates that just looking at the public interface of this class you’d have absolutely no idea that it uses ConfigurationManager internally:
1: public class SomeClass
2: {
3: public void SomeMethod()
4: {
5: int value = int.Parse(ConfigurationManager.AppSettings["TheValue"]);
6: }
7: }
At least with the code above you may go investigating “what lies beneath” and find the hidden dependency but what if you came across this:
My guess is like me you’d anticipate that the class had been sorted for dependency injection and only needed the 2 dependencies that its constructor was advertising and it wasn’t until you got bitten by a problem that you’d look at the code and find:
1: public class SomeClass
2: {
3: private readonly IDependency1 _firstDependency;
4: private readonly IDependency2 _secondDependency;
5:
6: public public SomeClass(IDependency1 firstDependency, IDependency2 secondDependency)
7: {
8: _firstDependency = firstDependency;
9: _secondDependency = secondDependency;
10: }
11:
12: public void SomeMethod()
13: {
14: string theSetting = ConfigurationManager.AppSettings["TheValue"];
15:
16: theSetting = theSetting + "ArbitaryValue";
17:
18: _secondDependency.TheSetting = theSetting;
19:
20: }
21: }
The code is written in .Net 4.0 but should work with .Net 2.0 and above if recompiled to target whatever version of the framework you are working with. For brevities sake I’m just going to show the second code snippet using IConfigurationManager which makes the code look like this;
1: public class SomeClass
2: {
3: private readonly IConfigurationManager _configurationManager;
4: .....
5:
6: public SomeClass(IConfigurationManager configurationManager, IDependency1 firstDependency,
7: IDependency2 secondDependency)
8: {....}
9:
10: public void SomeMethod()
11: {
12: string theSetting = _configurationManager.AppSettings["TheValue"];
13:
14: theSetting = theSetting + "ArbitaryValue";
15:
16: _secondDependency.TheSetting = theSetting;
17:
18: }
19: }
The actual IConfigurationManager project contains the implementations of both ConfigurationManager and WebConfigurationManager (plus tests) to show that you can use IConfigurationManager to replace either of these classes. Currently only the more common methods & properties have been implemented as following the principle of YAGNI I’ve not bothered adding methods such as OpenExeConfiguration that I don’t need at the moment.
The one extra thing that I have added is the ability to be able to return a strongly typed custom configuration section rather than retrieving a section as an object and then casting it, so instead of :
1: var sect = ConfigurationManager.GetSection("sampleSection")as SampleSectionProvider;
1: var sect = _configurationManager.GetSection<SampleSectionProvider>("sampleSection");
If you are using ConfigurationManager then I strongly recommend trying out IConfigurationManager, if not for you then for the person who has to maintain the code in a few months time