13

I'm trying to load modules into my application dynamically, but I want to specify separate app.config files for each one.

Say I have following app.config setting for main app:

<appSettings>
  <add key="House" value="Stark"/>
  <add key="Motto" value="Winter is coming."/>
</appSettings>

And another for library that I load using Assembly.LoadFrom:

<appSettings>
  <add key="House" value="Lannister"/>
  <add key="Motto" value="Hear me roar!"/>
</appSettings>

Both libraries have a class implementing the same interface, with the following method:

public string Name
{
    get { return ConfigurationManager.AppSettings["House"]; }
}

And sure enough calls to Name from both main class and loaded assembly class output Stark.

Is there a way to make main app use its own app.config and each loaded assembly use theirs? Names of config files are different in the output, so that should be possible I think.

Grozz
  • 8,317
  • 4
  • 38
  • 53
  • 4
    Think your looking for `ConfigurationManager.OpenExeConfiguration`RE http://www.codeproject.com/Articles/19675/Cracking-the-Mysteries-of-NET-2-0-Configuration – Luke Hutton Aug 16 '12 at 18:58

3 Answers3

15

Ok, here's the simple solution I ended up with: Create the follow function in the utility library:

public static Configuration LoadConfig()
{
    Assembly currentAssembly = Assembly.GetCallingAssembly();
    return ConfigurationManager.OpenExeConfiguration(currentAssembly.Location);
}

Using it in dynamically loaded libraries like this:

private static readonly Configuration Config = ConfigHelpers.LoadConfig();

No matter how that library gets loaded it uses the correct config file.

Edit: This might be the better solution for loading files into ASP.NET applications:

public static Configuration LoadConfig()
{
    Assembly currentAssembly = Assembly.GetCallingAssembly();
    string configPath = new Uri(currentAssembly.CodeBase).LocalPath;
    return ConfigurationManager.OpenExeConfiguration(configPath);
}

To copy file after build you might want to add the following line to post-build events for asp app (pulling the config from library):

copy "$(SolutionDir)<YourLibProjectName>\$(OutDir)$(Configuration)\<YourLibProjectName>.dll.config" "$(ProjectDir)$(OutDir)"
Grozz
  • 8,317
  • 4
  • 38
  • 53
  • In my case I needed to use `GetEntryAssembly` instead `GetCallingAssembly` because my executable calls another `dll` and this `dll` load the dynamic assembly. The .config was from the executable :) – Only a Curious Mind Jun 06 '16 at 20:22
4

As far as I know, you need separate application domains for the app.config to work separately. The creation of an AppDomainSetup allows you to specify which config file to use. Here's how I do it:

try
{
  //Create the new application domain
  AppDomainSetup ads = new AppDomainSetup();
  ads.ApplicationBase = Path.GetDirectoryName(config.ExePath) + @"\";
  ads.ConfigurationFile = 
    Path.GetDirectoryName(config.ExePath) + @"\" + config.ExeName + ".config";
  ads.ShadowCopyFiles = "false";
  ads.ApplicationName = config.ExeName;

  AppDomain newDomain = AppDomain.CreateDomain(config.ExeName + " Domain", 
    AppDomain.CurrentDomain.Evidence, ads);

  //Execute the application in the new appdomain
  retValue = newDomain.ExecuteAssembly(config.ExePath, 
    AppDomain.CurrentDomain.Evidence, null);

  //Unload the application domain
  AppDomain.Unload(newDomain);
}
catch (Exception e)
{
  Trace.WriteLine("APPLICATION LOADER: Failed to start application at:  " + 
    config.ExePath);
  HandleTerminalError(e);
}

Another way you could go about getting the desired effect would be to implement your configuration values inside a resource file compiled into each of your DLLs. A simple interface over the configuration object would allow you to switch out looking in an app.config versus looking in a resource file.

superjos
  • 12,189
  • 6
  • 89
  • 134
Josh
  • 10,352
  • 12
  • 58
  • 109
1

It may work if you change the code little bit:

public string Name
{
    get { 
        Configuration conf = ConfigurationManager.OpenExeConfiguration("library.dll");
        return conf.AppSettings.Settings["House"].Value; 
    }
}
Sudheer
  • 11
  • 1