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.dl l" then the config should be named "Hello.World.dl l.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" ?>
<configuratio n>
<configSections >
<section name="assemblyS ettings"
type="System.Co nfiguration.Dic tionarySectionH andler" />
<section name="otherAsse mblySettings"
type="System.Co nfiguration.Dic tionarySectionH andler" />
</configSections>
<assemblySettin gs>
<add key="SomeParam1 " value="SomeValu e1"/>
<add key="SomeParam2 " value="SomeValu e2"/>
<add key="SomeParam3 " value="SomeValu e3"/>
</assemblySetting s>
<otherAssemblyS ettings>
<add key="SomeOtherP aram1" value="SomeOthe rValue1"/>
<add key="SomeOtherP aram2" value="SomeOthe rValue2"/>
<add key="SomeOtherP aram3" value="SomeOthe rValue3"/>
</otherAssemblySe ttings>
</configuration>
(d) from your code, you can get the two separate config sections doing
something like (not compiled/tested):
AssemblyConfig m_assemblyConfi g = new
AssemblyConfig( Assembly.GetCal lingAssembly()) ;
AssemblyConfig m_otherConfig = new
AssemblyConfig( Assembly.GetCal lingAssembly(), @"otherAssembly Settings");
string someSetting = m_assemblyConfi g[@"SomeParam1 "];
string someOtherSettin g = m_otherConfig[@"SomeOtherPara m1"];
Here's what the main code looks like (again not compiled/tested):
using System;
using System.Reflecti on;
using System.Collecti ons;
using System.Xml;
using System.Configur ation;
using System.Runtime. CompilerService s;
namespace Put.Your.Namesp ace.Here
{
public class AssemblyConfig
{
[MethodImpl(Meth odImplOptions.N oInlining)]
public AssemblyConfig( ) : this(Assembly.G etCallingAssemb ly())
{
}
public AssemblyConfig( Assembly assembly)
{
m_settings = GetConfig(assem bly);
}
public AssemblyConfig( string nodeName)
{
m_settings = GetConfig(Assem bly.GetCallingA ssembly(), nodeName);
}
public AssemblyConfig( Assembly assembly, string nodeName)
{
m_settings = GetConfig(assem bly, 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(Assem bly.GetCallingA ssembly());
}
public static IDictionary GetConfig(Assem bly assembly)
{
return GetConfig(assem bly, @"assemblySetti ngs");
}
public static IDictionary GetConfig(Assem bly assembly, string
nodeName)
{
IDictionary dictionary = null;
string configFile = assembly.CodeBa se + @".config";
XmlDocument configDocument = new XmlDocument();
configDocument. Load(new XmlTextReader(c onfigFile));
XmlNodeList nodes = configDocument. GetElementsByTa gName(nodeName) ;
foreach (XmlNode node in nodes)
{
if (node.LocalName == nodeName)
{
DictionarySecti onHandler sectionHandler = new
DictionarySecti onHandler();
dictionary = (IDictionary)se ctionHandler.Cr eate(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
--
Patrick Simpe-Asante
MCAD, MSCD.Net
"Peter Bradley" wrote:
OK. A bit behind the times, I know; but we're just moving over to .NET 2.0.
How on earth do you manage configuration settings in a class library in .NET
2.0? In version 1.1, we used a handy class called AssemblySetting s that
someone (I forget his name) had written. When the class library was
finished, you deployed it to the GAC and put the configuration files in the
GAC with the class library assembly. This no longer works. In fact trying
to get configuration data from anywhere but the calling executable falls
over.
This can't be correct. Our n-Tier architecture uses class libraries to
access data from the database and needs to obtain a connection string from a
configuration file. It's no good putting the configuration in the calling
executable because the calling executable does not know anything about the
database, and anyway the whole point of a class library is that it can be
called by many other objects. We don't want the same configuration data
spread all over the place.
Surely there's a way to fix this. Does anyone know how?
Peter (spitting blood and calling Microsoft all sorts of things you don't
want to hear)