Reputation: 30857
After creating settings for each dll
, a .dll.config
file is generated. If that dll
be part of an asp.net application, how to keep this configurations separate for each dll
and don't merge them into web.config
?
Example: I have a GMailSender class library (DLL) which sends email via GMail servers. All you need is an instance of GMailSender, like this:
GMailSender gms = new GMailSender();
gms.To = "[email protected]";
gms.Subject = "System.Configuration dilemma";
gms.Body = "Can anyone help me with this question ?";
gms.Send();
Consider GMailSender
is inside GMailSender.dll
and it's configuration file is GMailSender.dll.config
and the username and password of GMail account are inside it.
I want this DLL
use the config file of itself (both dll and config in the same directory, i.e in Bin
folder of an ASP.NET application) or beside a desktop application. This way the GMailSender is independent of who is using him for retrieving it's configurations (current AppDomain
who has loaded this DLL
).
I want this without reconstructing the wheel (no custom configuration classes). I guess its possible with System.Configuration
but this namespace is probably the worst designed of .NET !
Please don't tell why you designed so that ...
This is a plug-in
based design and finally MEF
do some kind of it now in .NET 4.0, but there's the same problem for Parts
configurations. With MEF
at least I don't need anymore to argue for plugin-based
design advantages.
Upvotes: 3
Views: 1026
Reputation: 8282
What you need can be achieved using Custom Configuration Sections. This MSDN article provides some details and samples on how to implement such config sections.
If you need simple key/value configs, like in the appSettings section, then creating a custom configuration section is quite simple.
The first thing you need to do is define your config section inside web.config:
<configSections>
<section name="GmailSettings" restartOnExternalChanges="true" type="System.Configuration.NameValueFileSectionHandler" />
</configSections>
Now inside the web.config file you can declare the GmailSettings section and set the location of the external config file that you are going to use for that setting:
<GmailSettings configSource="GmailSettings.config"></GmailSettings>
configSource specifies the name and location of the external config file used for defining the GmailSettings section. Please note the restartOnExternalChanges
attribute used when defining the section. Set it to true if you want the application to be automatically restarted when you modify the GmailSettings.config file (as it does when you modify the web.config file).
Below is an example of how to implement the GmailSettings.config file:
<?xml version="1.0"?>
<GmailSettings>
<add key="userName" value="blabla"/>
<add key="password" value="moreBla"/>
</GmailSettings>
You can access the settings from GmailSettings using the ConfigurationManager.GetSection()
method or by implementing a helper class like the one below:
public class GmailSettings
{
private static readonly GmailSettings _instance = new GmailSettings();
private NameValueCollection _settings = ConfigurationManager.GetSection("GmailSettings") as NameValueCollection;
public static GmailSettings Instance
{
get { return _instance; }
}
public string this[string key]
{
get { return _settings[key]; }
}
}
The settings can now be accessed like GmailSettings.Instance["userName"]
.
Hope this helps.
Upvotes: 4
Reputation:
What you are looking for cannot be done out of the box. Also, ASP.NET do a shadow copy on DLLs so writing a custom configuration class is not easy to. Your DLLs are not run from Bin folder. THey run from appDomainSetup.CachePath
so the *.dll.config files are not beside their assemblies at run-time.
You can add a refrence to *.dll.config files inside web.config instead of copy/paste all key/values from DLL configuration files into web.config; This is possible by using File
element in web.config.
I think this is not intended by designers in past and composition became popular in recent years.
Upvotes: 1
Reputation: 24515
I would add configuration settings to the web.config file and call:
ConfigurationManager.AppSettings["DllName.MySetting"]
This means all configuration settings are in one place and not in the Bin folder.
Upvotes: 0
Reputation: 74277
To do what I believe you want to do -- give your DLL a configuration file about which referencing assemblies need no nothing, you can[1] do something like the following code.
static class DllConfigurationFactory
{
public static Configuration GetConfigurationInstance()
{
string callingAssemblyPath = Assembly.GetCallingAssembly().Location ;
string configFilePath = string.Concat( callingAssemblyPath , ".config" ) ;
// getAttributes hurls with a multitude of exceptions
FileAttributes attributes = File.GetAttributes( configFilePath ) ;
bool isDirectory = ( (attributes&FileAttributes.Directory) == FileAttributes.Directory ? true : false ) ;
if ( isDirectory )
{
throw new FileNotFoundException() ;
}
// check for (and die with an SecurityException) if we dont' have read access
new FileIOPermission( FileIOPermissionAccess.Read , configFilePath ).Demand() ;
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = configFilePath ;
Configuration instance = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
return instance ;
}
}
This factory method does the following:
Finds the fully-qualified path of the assembly of the caller ((not that of the assembly containing the factory -- it, after all, might be in its own DLL).
Tacks a ".config" on to the end of that path (thus yielding something like 'C:\usr/bin/local/foo/myAssembly.dll.config'.
Ensures that that file exists and is readable, throwing an appropriate exception if not.
Using that path as the source, instantiates a new instance of System.Configuration.Configuration and returns it to the caller.
Notes
Good Luck!
[1] TMTOWTDI as they say in Perl (There's more than one way to do it). You could also, for instance, create a custom section and park it in machine.config.
And there's no requirement that you use the .Net configuration system for this: your factory method could slurp in any arbitrary XML and deserialize it into an object of your choice. This would give you a strongly typed, bound access to the configuration properties, albeit at the expense of automatic refreshing when the config file gets changed. Although...you could also just put a wrapper around the standard Configuration object that would provide the same thing.
Upvotes: 1
Reputation: 26874
Creating an App.config for a DLL is not a good practice. Configuration belongs to the running application. The class library dll is supposed only to provide services to the calling application.
If you wrote the DLLs on your own, then you can make these DLL's code prefer their own independent .dll.config file rather than the global App.config/Web.config (in your ASP.NET case) using a trick.
This method allows you to open any executable file's .config file, but no one prevents you from calling it with "Mydll.dll" as argument, and has the same effect. But this works only if you can access these DLL's code.
A good practice is to use configuration sections, which are easy to maintain when merged inside a single configuration file.
Upvotes: 1