Reputation: 2198
I am trying to access a set of connection strings from an arbitrary configuration file provided at runtime by way of the ConfigurationManager.ConnectionStrings
static property. Application code expects the connection string to be in this collection and I need to provide a new value without editing the default configuration file.
I have determined that I can use System.Configuration.ConfigurationManager.OpenMappedExeConfiguration
to load connection strings from an arbitrary configuration file by using System.Configuration.ExeConfigurationFileMap
, e.g.:
using System.Configuration;
var config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap{ExeConfigFilename = 'some.config'}, ConfigurationUserLevel.None);
config.RefreshSection(config.ConnectionStrings.SectionInformation.SectionName);
In this context, I'd expect to be able to access the connection strings loaded from some.config
from the static ConfigurationManager.ConnectionStrings
property but this seems to hold only what was available in the application configuration defaults.
Is it possible to mask or copy into the default configuration to update the value of the static ConfigurationManager.ConnectionStrings
property? Alternatively, is any way to redefine the default configuration to a new configuration file defined at runtime, hopefully leading to the desired end result?
Upvotes: 0
Views: 743
Reputation: 2198
An interesting reflection workaround I discovered allows changing the non-public System.Configuration.ConfigurationElementCollection.bReadOnly property of System.Configuration.ConfigurationManager.ConnectionStrings by using reflection:
using System;
using System.Configuration;
var connectionString = "...";
var connectionStringSetting = new ConnectionStringSettings("OrionDB", connectionString);
var field = ConfigurationElementCollection.GetField("bReadOnly",
Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance);
var connectionStrings = ConfigurationManager.ConnectionStrings;
field.SetValue(connectionStrings, false);
connectionStrings.Add(connectionStringSetting);
This gave me the desired behaviour while not necessarily the intended use of the static ConfigurationManager
properties.
Upvotes: 0
Reputation: 29207
The short answer is no. The ConnectionStrings
and AppSettings
properties of ConfigurationManager
are just for convenience to read from the default configuration. You can load other configurations, but you can't change the behavior of those methods.
If this Configuration
is properly loaded:
var config = ConfigurationManager.OpenMappedExeConfiguration(
new ExeConfigurationFileMap{ExeConfigFilename = 'some.config'}.
ConfigurationUserLevel.None);
Then you can get the connection string from there.
var connectionString = config.ConnectionStrings.ConnectionStrings["connectionName"]
.ConnectionString;
A part of the answer is not to use ConfigurationManager
or Configuration
from deep within your classes. You can either use dependency injection, or, worst case scenario, create your own static class to use instead of ConfigurationManager
. But this is a perfect example of why you don't want a class accessing this directly, because you can't change its behavior.
Upvotes: 1