Background
I have a number of services that are implemented by components that depend on a connection string to be created - for instance:
public interface IImportantRepository { ... }
public class ImportantRepository
{
public ImportantRepository(IOracleConnection connection) { ... }
public ImportantRepository(string connectionString) { ... } // rarely my constructor of choice, but included for clarity
}
I generally prefer the first constructor to the second because in order to consume a connection string I must create a connection with it, which will in turn require resolution of IOracleConnection
with a string
dependency.
My IImportantController
has a single constructor and parameter of IImportantRepository
. My IControllerFactory
is the composition root (not counting the bootstrapper) and uses IWindsorContainer.Resolve<T>()
at runtime to activate the right controller for the job.
So I suppose the whole thing looks like this at bootstrap-time:
Global.Asax => ControllerBuilder.Current => MyControllerFactory : IControllerFactory
and this at request time:
IControllerFactory => IImportantController => IImportantRepository => IOracleConnection
Motivation
Now, in one application, IOracleConnection
(and the underlying string that builds it) may be known when:
- The application is designed (a fictitious connection string for testing)
- The application is compiled (a connection string completely determined by a build var)
- The application is deployed (a connection string set in a
web.config
transformation) - The application is bootstrapped (a connection string set in a configuration source read only once)
- The application handles a certain type of request (say, "typically" but not "always" you want to display data from
ProductionDb
) - The application handles a request in which the connection is parameterized (a request to manage
Important
stuff in theChicagoDb
instead of theNewYorkDb
, or whatever) - The application handles a request in which the session or user details completely determine the connection (10 percent of users live on
Db1
and the rest onDb2
by design)
Question
How would you write maintainable code without violating DRY too much that achieves all of these potential uses of the same dependency for the same graph simultaneously?