Linqpad is the only scripting like environment where I can work with my large code base. The reason it is the only environment that works for me is that other solutions (ironpython etc) always fail to properly load configuration from app.config, but linqpad.config works
The problem is, I have multiple config files and every time I want to use one of them for a script, I have to go to linqpad installation directory, rename the right config file to linqpad.config and restart linq. Hardly productive.
I've tried to set the file through:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");
but it did not have any effect. Is there any way I can change the config file that will be used in the Main() method of a C# Program in Linqpad? If I could make a call to a function that sets the config file to be used and then run the rest of my code, that'd be great.
Example Linq Query:
void Main()
{
var configPath = Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "app.config");
// Load custom config
var configProxy = new ConfigurationProxy(configPath);
if (!configProxy.InjectToConfigurationManager())
{
Trace.TraceError("Cannot load config from " + configPath);
throw new InvalidOperationException("Cannot load config " + configPath);
}
ConfigurationManager.AppSettings["LogPath"].Dump();
}
Add this class to your Linq query:
/// <summary>
/// A custom config injector.
/// </summary>
public sealed class ConfigurationProxy : IInternalConfigSystem
{
/// <summary>
/// The custom sections
/// </summary>
private readonly Dictionary<string, IConfigurationSectionHandler> customSections;
/// <summary>
/// The configuration
/// </summary>
private Configuration config;
/// <summary>
/// Initializes a new instance of the <see cref="ConfigurationProxy"/> class.
/// </summary>
/// <param name="fileName">
/// Name of the file.
/// </param>
/// <remarks>
/// this is called filename but really it's the path as needed
/// it defaults to checking the directory you're running in.
/// </remarks>
public ConfigurationProxy(string fileName)
{
this.customSections = new Dictionary<string, IConfigurationSectionHandler>();
if (!this.Load(fileName))
{
throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "File: {0} could not be found or was not a valid configuration file.", this.config.FilePath));
}
}
/// <summary>
/// Gets the configuration.
/// </summary>
public Configuration Configuration
{
get
{
return this.config;
}
}
/// <summary>
/// Returns the configuration object based on the specified key.
/// </summary>
/// <param name="configKey">The configuration key value.</param>
/// <returns>
/// A configuration object.
/// </returns>
public object GetSection(string configKey)
{
if (configKey == "appSettings")
{
return this.BuildAppSettings();
}
object sect = this.config.GetSection(configKey);
if (this.customSections.ContainsKey(configKey) && sect != null)
{
var xml = new XmlDocument();
xml.LoadXml(((ConfigurationSection)sect).SectionInformation.GetRawXml());
// I have no idea what I should normally be passing through in the first
// two params, but I never use them in my config handlers so I opted not to
// worry about it and just pass through something...
sect = this.customSections[configKey].Create(this.config, this.config.EvaluationContext, xml.FirstChild);
}
return sect;
}
/// <summary>
/// The refresh config.
/// </summary>
/// <param name="sectionName">
/// The section name.
/// </param>
public void RefreshConfig(string sectionName)
{
// I suppose this will work. Reload the whole file?
this.Load(this.config.FilePath);
}
/// <summary>
/// Gets a value indicating whether supports user config.
/// </summary>
public bool SupportsUserConfig
{
get
{
return false;
}
}
/// <summary>
/// Injects to configuration manager.
/// </summary>
/// <returns>Whether the configuration was injected</returns>
public bool InjectToConfigurationManager()
{
// inject self into ConfigurationManager
var configSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic);
if (configSystem != null)
{
configSystem.SetValue(null, this);
}
// lame check, but it's something
if (ConfigurationManager.AppSettings.Count == this.config.AppSettings.Settings.Count)
{
return true;
}
return false;
}
/// <summary>
/// Loads the specified file.
/// </summary>
/// <param name="file">
/// The file.
/// </param>
/// <returns>
/// Is file loaded
/// </returns>
private bool Load(string file)
{
var map = new ExeConfigurationFileMap { ExeConfigFilename = file };
this.config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var xml = new XmlDocument();
using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
xml.Load(stream);
}
// var cfgSections = xml.GetElementsByTagName("configSections");
// if (cfgSections.Count > 0)
// {
// foreach (XmlNode node in cfgSections[0].ChildNodes)
// {
// var type = System.Activator.CreateInstance(
// Type.GetType(node.Attributes["type"].Value))
// as IConfigurationSectionHandler;
// if (type == null) continue;
// customSections.Add(node.Attributes["name"].Value, type);
// }
// }
return this.config.HasFile;
}
/// <summary>
/// The build app settings.
/// </summary>
/// <returns>
/// The <see cref="NameValueCollection"/>.
/// </returns>
private NameValueCollection BuildAppSettings()
{
var coll = new NameValueCollection();
foreach (var key in this.config.AppSettings.Settings.AllKeys)
{
coll.Add(key, this.config.AppSettings.Settings[key].Value);
}
return coll;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With