Hi Peter,
I have to admit that I belong to the school of thought that says config's
should generally be more closely aligned to the calling exe's - however I
recently had to build a system that supported the use of plug-in's (for
loose-coupling purposes) that could be dropped into a folder and be
immediately available for use by the rest of the system. These plug-ins were
contained in assemblies and so using config files that travelled with the
assembly was what I opted for.
I also use .NET v2.0 and also did find some v1.1 code on the web that
roughly did what I wanted, although I remember having to make a few changes
to it to get it to work (the changes I made were minimal) - like you, I can't
remember the name of the author though (who really ought to get credit for
the code)... Just in case this wasn't the same code you have, I'll quickly
cover the usage scenario...
To use it, you need to:
(a) name the config file the same as the assembly, but with ".config"
appended to the end ofthe name - so e.g., if your assembly is called
"Hello.World.dll" then the config should be named "Hello.World.dll.config"
(b) make sure the config is in the same folder as the assembly
(c) have your config look something like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="assemblySettings"
type="System.Configuration.DictionarySectionHandler" />
<section name="otherAssemblySettings"
type="System.Configuration.DictionarySectionHandler" />
</configSections>
<assemblySettings>
<add key="SomeParam1" value="SomeValue1"/>
<add key="SomeParam2" value="SomeValue2"/>
<add key="SomeParam3" value="SomeValue3"/>
</assemblySettings>
<otherAssemblySettings>
<add key="SomeOtherParam1" value="SomeOtherValue1"/>
<add key="SomeOtherParam2" value="SomeOtherValue2"/>
<add key="SomeOtherParam3" value="SomeOtherValue3"/>
</otherAssemblySettings>
</configuration>
(d) from your code, you can get the two separate config sections doing
something like (not compiled/tested):
AssemblyConfig m_assemblyConfig = new
AssemblyConfig(Assembly.GetCallingAssembly());
AssemblyConfig m_otherConfig = new
AssemblyConfig(Assembly.GetCallingAssembly(), @"otherAssemblySettings");
string someSetting = m_assemblyConfig[@"SomeParam1"];
string someOtherSetting = m_otherConfig[@"SomeOtherParam1"];
Here's what the main code looks like (again not compiled/tested):
using System;
using System.Reflection;
using System.Collections;
using System.Xml;
using System.Configuration;
using System.Runtime.CompilerServices;
namespace Put.Your.Namespace.Here
{
public class AssemblyConfig
{
[MethodImpl(MethodImplOptions.NoInlining)]
public AssemblyConfig() : this(Assembly.GetCallingAssembly())
{
}
public AssemblyConfig(Assembly assembly)
{
m_settings = GetConfig(assembly);
}
public AssemblyConfig(string nodeName)
{
m_settings = GetConfig(Assembly.GetCallingAssembly(), nodeName);
}
public AssemblyConfig(Assembly assembly, string nodeName)
{
m_settings = GetConfig(assembly, nodeName);
}
public string this[string key]
{
get
{
string settingValue = null;
if (m_settings != null)
{
settingValue = m_settings[key] as string;
}
return (settingValue == null ? "" : settingValue);
}
}
public IDictionary Settings
{
get { return m_settings; }
}
protected IDictionary m_settings;
public static IDictionary GetConfig()
{
return GetConfig(Assembly.GetCallingAssembly());
}
public static IDictionary GetConfig(Assembly assembly)
{
return GetConfig(assembly, @"assemblySettings");
}
public static IDictionary GetConfig(Assembly assembly, string
nodeName)
{
IDictionary dictionary = null;
string configFile = assembly.CodeBase + @".config";
XmlDocument configDocument = new XmlDocument();
configDocument.Load(new XmlTextReader(configFile));
XmlNodeList nodes = configDocument.GetElementsByTagName(nodeName);
foreach (XmlNode node in nodes)
{
if (node.LocalName == nodeName)
{
DictionarySectionHandler sectionHandler = new
DictionarySectionHandler();
dictionary = (IDictionary)sectionHandler.Create(null,
null, node);
break;
}
}
return dictionary;
}
}
}
One last thing to mention - I have definitely got this working in .NET v2.0
with no probs, however this was in a non-GAC scenario (the plug-ins that used
this code were not hosted in the GAC) - if tihs code doesn't work in your
setup, then it may well have something to do with OS/.Net
permissioning/security and/or the fact that your assemblies are being hosted
inside of the GAC (i'm too tired to think why this late in the day
)..
Hope this helps you out...
Kind regards,
Patrick