Подтвердить что ты не робот

Конфигурация приложения для динамически загружаемых сборок

Я пытаюсь загрузить модули в мое приложение динамически, но я хочу указать отдельные файлы app.config для каждого из них.

Скажем, у меня есть следующий параметр app.config для основного приложения:

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

И еще один для библиотеки, которую я загружаю с помощью Assembly.LoadFrom:

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

Обе библиотеки имеют класс, реализующий один и тот же интерфейс, со следующим методом:

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

И, конечно же, вызывает вызов Name из основного класса и загруженного класса сборки класса Stark.

Есть ли способ заставить основное приложение использовать собственный app.config, и каждая загруженная сборка использует их? Имена конфигурационных файлов различаются на выходе, поэтому я должен думать, что это возможно.

4b9b3361

Ответ 1

Хорошо, здесь простое решение, с которым я столкнулся: Создайте следующую функцию в библиотеке утилиты:

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

Использование в динамически загружаемых библиотеках:

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

Независимо от того, как загружается эта библиотека, он использует правильный файл конфигурации.

Edit: Это может быть лучшим решением для загрузки файлов в приложения ASP.NET:

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

Чтобы скопировать файл после сборки, вы можете добавить следующую строку для post-build событий для asp-приложения (вытаскивая конфигурацию из библиотеки):

copy "$(SolutionDir)<YourLibProjectName>\$(OutDir)$(Configuration)\<YourLibProjectName>.dll.config" "$(ProjectDir)$(OutDir)"

Ответ 2

Насколько мне известно, для работы приложения необходимо, чтобы отдельные домены приложений работали отдельно. Создание AppDomainSetup позволяет указать, какой конфигурационный файл использовать. Вот как я это делаю:

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);
}

Еще один способ, которым вы могли бы получить желаемый эффект, - реализовать ваши значения конфигурации внутри файла ресурсов, скомпилированного в каждую из ваших DLL. Простой интерфейс над объектом конфигурации позволит вам отключить поиск в app.config и посмотреть в файле ресурсов.

Ответ 3

Это может сработать, если вы немного измените код:

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