I have a class library that is usually called from a .net console or web application. It integrates with various components, and relies on an app.config or web.config.
If I want to utilise the class library from script (i.e. IronPython), how can I get the script to utilise the config file? Ideally I want to be able to choose the config file when I run the script, or by convention (config file sitting alongside the script file).
I don't want to change the ipy.exe.config if possible as this wouldn't scale for multiple configurations without having multiple copies of IronPython?
Any alternatives?
Application configuration in ASP.NET Core is performed using one or more configuration providers. Configuration providers read configuration data from key-value pairs using a variety of configuration sources: Settings files, such as appsettings. json.
By adding an application configuration file (app. config file) to a C# project, you can customize how the common language runtime locates and loads assembly files. For more information about application configuration files, see How the runtime locates assemblies (. NET Framework).
In Solution Explorer, right-click the project node, and then select Add > New Item. The Add New Item dialog box appears. Expand Installed > Visual C# Items. In the middle pane, select the Application Configuration File template.
I have a working solution with code sample. See my blog: http://technomosh.blogspot.com/2012/01/using-appconfig-in-ironpython.html
It requires a special proxy class which is injected to the ConfigurationManager.
Here is the source for the ConfigurationProxy library:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Configuration.Internal;
using System.Xml;
using System.Collections.Specialized;
using System.Reflection;
using System.IO;
namespace IronPythonUtilities
{
/// <summary>
/// A custom app.config injector for use with IronPython code that needs configuration files.
/// The code was taken and modified from the great work by Tom E Stephens:
/// http://tomestephens.com/2011/02/making-ironpython-work-overriding-the-configurationmanager/
/// </summary>
public sealed class ConfigurationProxy : IInternalConfigSystem
{
Configuration config;
Dictionary<string, IConfigurationSectionHandler> customSections;
// this is called filename but really it's the path as needed...
// it defaults to checking the directory you're running in.
public ConfigurationProxy(string fileName)
{
customSections = new Dictionary<string, IConfigurationSectionHandler>();
if (!Load(fileName))
throw new ConfigurationErrorsException(string.Format(
"File: {0} could not be found or was not a valid cofiguration file.",
config.FilePath));
}
private bool Load(string file)
{
var map = new ExeConfigurationFileMap { ExeConfigFilename = file };
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 config.HasFile;
}
public Configuration Configuration
{
get { return config; }
}
#region IInternalConfigSystem Members
public object GetSection(string configKey)
{
if (configKey == "appSettings")
return BuildAppSettings();
object sect = config.GetSection(configKey);
if (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 confighandlers so I opted not to
// worry about it and just pass through something...
sect = customSections[configKey].Create(config,
config.EvaluationContext,
xml.FirstChild);
}
return sect;
}
public void RefreshConfig(string sectionName)
{
// I suppose this will work. Reload the whole file?
Load(config.FilePath);
}
public bool SupportsUserConfig
{
get { return false; }
}
#endregion
private NameValueCollection BuildAppSettings()
{
var coll = new NameValueCollection();
foreach (var key in config.AppSettings.Settings.AllKeys)
coll.Add(key, config.AppSettings.Settings[key].Value);
return coll;
}
public bool InjectToConfigurationManager()
{
// inject self into ConfigurationManager
var configSystem = typeof(ConfigurationManager).GetField("s_configSystem",
BindingFlags.Static | BindingFlags.NonPublic);
configSystem.SetValue(null, this);
// lame check, but it's something
if (ConfigurationManager.AppSettings.Count == config.AppSettings.Settings.Count)
return true;
return false;
}
}
}
and here is how it can be loaded from Python:
import clr
clr.AddReferenceToFile('ConfigurationProxy.dll')
from IronPythonUtilities import ConfigurationProxy
def override(filename):
proxy = ConfigurationProxy(filename)
return proxy.InjectToConfigurationManager()
Finally, a usage sample:
import configproxy
import sys
if not configproxy.override('blogsample.config'):
print "could not load configuration file"
sys.exit(1)
import clr
clr.AddReference('System.Configuration')
from System.Configuration import *
connstr = ConfigurationManager.ConnectionStrings['TestConnStr']
print "The configuration string is {0}".format(connstr)
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