I have an Interface IApplicationConfig
that basically holds ConnectionStrings like for the Database, Blob Storage and other stuff. For every "executable" Project in my solution, like websites, command line tools etc. there is a concrete implementation of that interface which is configured to be resolved via dependency injection.
My question is, where should I put these IApplicationConfig
-Implementations?
Next to my web.config
/app.config
in each "executable" Project?
Or in Infrastructure, as Project1Config.cs
, Project2Config.cs
etc.?
The way I have implemented managing configuration in one of my applications which is structured following the rules of Onion Architecture is as follows.
In this particular case I'm considering managing configuration (for instance logging as well) as an infrastructural concern, so that means that it's clearly not part of my application core. This is because it's an other layer.
To demonstrate the infrastructural concern please take a look a diagram below:
* Image linked from the blog of Shawn J Lee.
Here you can see that logging takes place in the infrastructure slice or layer, I have stated that managing configuration is also an infrastructural concern.
Now, if anywhere in your architecture if you need to get a hold of your configuration manager implementation, you just ask for your IApplicationConfig
in your constructors and get the proper implementation injected as per configured in your favorite DI container/framework. This is called as the Hollywood Principle or better yet Inversion Of Control.
Enough babbling you say? Now let's get straight to the technological demonstration...
You have asked about where to put actual implementations. I would structure these bits as:
Getting sleepy eh? Let's shift to higher gears now.
I will try to illustrate here the actual implementation details in short.
This is the layer where you put all the interface which the application core -and other layers as well- will work against or utilise.
Say we have IApplicationConfig.cs
:
public interface IApplicationConfig
{
ConnectionStringSettingsCollection GetConnectionStrings();
}
This is the place where you can have the actual implementation(s) of your IApplicationConfig
interface. Having this as a separate assembly is questionable but it's really just an implementation detail, I personally store all my configuration managing implementations here.
For instance an implementation of IApplicationConfig
could be as ApplicationConfig.cs
:
public class ApplicationConfig : IApplicationConfig
{
public ConnectionStringSettingsCollection GetConnectionStrings()
{
return ConfigurationManager.ConnectionStrings;
}
}
This is where you "link" your interfaces with the needed implementations. Here I'm using Ninject and have created a Ninject module for it calling it as ConfigModule
, a simple example:
public class ConfigModule : NinjectModule
{
Bind<IApplicationConfig>().To<ApplicationConfig>();
}
Usually these are the Composition Root or the entry point of your applications where you compose your object graph. Having said this we now just need to load our Ninject module:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
var modules = new List<INinjectModule>
{
new ConfigModule(),
new WhateverModule(),
...
};
kernel.Load(modules);
}
Having the interface contract and it's implementation separated, here you only need to add references to the:
And now you can use your implementation in whichever layer you want.
This example has been taken from an actual application of mine, if you disagree with naming things, I agree... it's not an easy thing to do.