Эквивалентен "app.config" для библиотеки (DLL)

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

Ответ 1

У вас может отдельный файл конфигурации, но вы должны будете прочитать его "вручную", ConfigurationManager.AppSettings["key"] будет читать только конфигурацию запущенной сборки.

Предполагая, что вы используете Visual Studio в качестве среды IDE, вы можете щелкнуть правой кнопкой мыши по нужному проекту → Добавить → Новый элемент → Файл конфигурации приложения

Это добавит App.config к папке проекта, поместите ваши настройки там под <appSettings>. Если вы не используете Visual Studio и добавляете файл вручную, обязательно укажите ему такое имя: DllName.dll.config, в противном случае приведенный ниже код не будет работать должным образом.

Теперь для чтения из этого файла есть такая функция:

string GetAppSetting(Configuration config, string key)
{
    KeyValueConfigurationElement element = config.AppSettings.Settings[key];
    if (element != null)
    {
        string value = element.Value;
        if (!string.IsNullOrEmpty(value))
            return value;
    }
    return string.Empty;
}

И использовать его:

Configuration config = null;
string exeConfigPath = this.GetType().Assembly.Location;
try
{
    config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception ex)
{
    //handle errror here.. means DLL has no sattelite configuration file.
}

if (config != null)
{
    string myValue = GetAppSetting(config, "myKey");
    ...
}

Вам также нужно добавить ссылку на пространство имен System.Configuration, чтобы иметь класс ConfigurationManager.

При создании проекта, помимо DLL, вы также будете иметь файл DllName.dll.config, который вы должны опубликовать с самой DLL.

Вышеприведенный базовый пример кода для тех, кто интересуется полномасштабным примером, см. этот другой ответ.

Ответ 2

К сожалению, у вас может быть только один файл app.config для каждого исполняемого файла, поэтому, если у вас есть DLL файлы, связанные с вашим приложением, они не могут иметь свои файлы app.config.

Решение: Вам не нужно класть файл App.config в проект библиотеки классов.
Вы помещаете файл App.config в приложение, ссылающееся на ваш класс библиотека dll.

Например, скажем, у нас есть библиотека классов с именем MyClasses.dll, которая использует файл app.config следующим образом:

string connect = 
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];

Теперь скажем, что у нас есть приложение Windows с именем MyApp.exe, которое ссылается на MyClasses.dll. Он будет содержать App.config с записью, такой как как:

<appSettings>
    <add key="MyClasses.ConnectionString"
         value="Connection string body goes here" />
</appSettings>

ИЛИ

Файл xml лучше всего подходит для app.config. Использовать xml serialize/deserialize as необходимо. Вы можете назвать это тем, что хотите. Если ваша конфигурация "статическая", и его не нужно менять, вы также можете добавить его в проект как встроенный ресурс.

Надеюсь, что это даст некоторую идею

Ответ 3

Конфигурационные файлы не привязаны к приложениям, а не в сборе. Поэтому вам нужно разместить разделы конфигурации библиотеки в каждом файле конфигурации приложения, использующем вашу библиотеку.

Тем не менее, неплохо было получить конфигурацию из файла конфигурации приложения, особенно раздела appSettings, в библиотеке классов. Если вашей библиотеке нужны параметры, они, вероятно, должны передаваться как аргументы метода в конструкторах, методах factory и т.д. Тем, кто звонит в вашу библиотеку. Это предотвращает случайное повторное использование приложений приложения, которые ожидались в библиотеке классов.

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

Подробнее о настраиваемых разделах конфигурации можно узнать на MSDN, а также У Фила Хаака есть хорошая статья.

Ответ 4

public class ConfigMan
{

    #region Memberes

    string _assemblyLocation;
    Configuration _configuration;

    #endregion


    #region Constructors

    /// <summary>
    /// Loads config file settings for libraries that use assembly.dll.config files
    /// </summary>
    /// <param name="assemblyLocation">The full path or UNC location of the loaded file that contains the manifest.</param>
    public ConfigMan(string assemblyLocation)
    {
        _assemblyLocation = assemblyLocation;
    }

    #endregion


    #region Properties

    Configuration Configuration
    {
        get
        {
            if (_configuration == null)
            {
                try
                {
                    _configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
                }
                catch (Exception exception)
                {
                }
            }
            return _configuration;
        }
    }

    #endregion


    #region Methods

    public string GetAppSetting(string key)
    {
        string result = string.Empty;
        if (Configuration != null)
        {
            KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key];
            if (keyValueConfigurationElement != null)
            {
                string value = keyValueConfigurationElement.Value;
                if (!string.IsNullOrEmpty(value)) result = value;
            }
        }
        return result;
    }

    #endregion

}

Просто для чего-то я реорганизовал верхний ответ в класс. Использование - это что-то вроде

ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");

Ответ 5

Если вы добавите настройки в проект библиотеки классов в Visual Studio (Свойства проекта, Настройки), он добавит файл app.config в ваш проект с соответствующими разделами userSettings/applatioNSettings и значениями по умолчанию для этих параметров из вашего Файл настроек.

Однако этот файл конфигурации не будет использоваться во время выполнения - вместо этого библиотека классов использует файл конфигурации своего хостинга.

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

Ответ 6

В ответ на исходный вопрос я обычно добавляю файл конфигурации в свой тестовый проект как ссылку; вы можете использовать атрибут DeploymentItem для добавления в папку Out тестового прогона.

[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
    .
    .
    .
    .
}

В ответ на комментарии, что сборки не могут быть специфичными для проекта, они могут и обеспечивают большую гибкость. при работе с каркасами IOC.

Ответ 7

В сборках

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

Если ваша сборка используется несколькими приложениями, каждое из этих приложений должно будет иметь эти записи в файле app.config.

Что бы я рекомендовал вам, это определить свойства классов в вашей сборке для этих значений, например

private string ExternalServicesUrl
{
  get
  {
    string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"];
    if (String.IsNullOrEmpty(externalServiceUrl))
      throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl");
    return externalServiceUrl;
  }
}

Здесь свойство ExternalServicesUrl получает свое значение из файла конфигурации приложения. Если в каком-либо приложении, использующем эту сборку, отсутствует этот параметр в файле конфигурации, вы получите исключение, ясно, что что-то пропало.

MissingConfigFileAppSettings - это обычное исключение. Вы можете создать другое исключение.

Конечно, лучший дизайн был бы для того, чтобы метод этих классов предоставлял эти значения в качестве параметров, а не полагался на настройку файла конфигурации. Таким образом, приложения, использующие эти классы, могут решить, где и как они обеспечивают эти значения.

Ответ 8

Используйте добавление существующего элемента, выберите конфигурацию приложения из проекта dll. Прежде чем нажимать кнопку "Добавить", используйте маленькую стрелку вниз в правой части кнопки "Добавить в качестве ссылки"

Я делаю это все время в своем dev.

Ответ 9

В настоящее время я создаю плагины для бренда розничного программного обеспечения, которые на самом деле являются библиотеками классов .net. В качестве требования каждый плагин необходимо настроить с помощью файла конфигурации. После небольшого исследования и тестирования я скомпилировал следующий класс. Это делает работу безупречно. Обратите внимание, что я не реализовал локальную обработку исключений в моем случае, потому что я перехватываю исключения на более высоком уровне.

Некоторая настройка может понадобиться, чтобы получить десятичную точку вправо, в случае десятичных знаков и удвоений, но она отлично работает для моей CultureInfo...

static class Settings
{
    static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
    static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);
    static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
    static NumberFormatInfo nfi = new NumberFormatInfo() 
    { 
        NumberGroupSeparator = "", 
        CurrencyDecimalSeparator = "." 
    };

    public static T Setting<T>(string name)
    {
        return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
    }
}

Пример файла App.Config

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

Использование:

  somebooleanvar = Settings.Setting<bool>("Enabled");
  somestringlvar = Settings.Setting<string>("ExportPath");
  someintvar =     Settings.Setting<int>("Seconds");
  somedoublevar =  Settings.Setting<double>("Ratio");

Кредиты для мастера магии и MattC

Ответ 10

Преамбула: я использую NET 2.0;

Решение, отправленное Yiannis Leoussis, приемлемо, но у меня была проблема с ним.

Во-первых, static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); возвращает null. Мне пришлось изменить его на static AppSettingSection = myDllConfig.AppSettings;

Затем return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); не имеет catch для исключений. Поэтому я изменил его

try
{
    return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
    return default(T);
}

Это работает очень хорошо, но если у вас есть другая dll, вы должны переписывать каждый раз код для каждой сборки. Итак, это моя версия для класса для создания экземпляра каждый раз, когда вам нужно.

public class Settings
{
    private AppSettingsSection _appSettings;
    private NumberFormatInfo _nfi;

    public Settings(Assembly currentAssembly)
    {
        UriBuilder uri = new UriBuilder(currentAssembly.CodeBase);
        string configPath = Uri.UnescapeDataString(uri.Path);
        Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath);
        _appSettings = myDllConfig.AppSettings;
        _nfi = new NumberFormatInfo() 
        { 
            NumberGroupSeparator = "", 
            CurrencyDecimalSeparator = "." 
        };
    }


    public T Setting<T>(string name)
    {
        try
        {
            return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi);
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }
}

Для конфигурации:

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

Используйте его как:

Settings _setting = new Settings(Assembly.GetExecutingAssembly());

somebooleanvar = _settings.Setting<bool>("Enabled");
somestringlvar = _settings.Setting<string>("ExportPath");
someintvar =     _settings.Setting<int>("Seconds");
somedoublevar =  _settings.Setting<double>("Ratio");

Ответ 11

Насколько мне известно, вам нужно скопировать + вставить разделы, которые вы хотите, из библиотеки .config в файл .config приложений. Вы получаете только 1 app.config для исполняемого экземпляра.

Ответ 12

Я столкнулся с той же проблемой и разрешил ее, создав статический класс Parameters после добавления в проект файла конфигурации приложения:

public static class Parameters
{
    // For a Web Application
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config");

    // For a Class Library
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config");

    public static string getParameter(string paramName)
    {
        string paramValue = string.Empty;

        using (Stream stream = File.OpenRead(PathConfig))
        {
            XDocument xdoc = XDocument.Load(stream);

            XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName);
            paramValue = element.Attribute("value").Value;
        }

        return paramValue;
    }
}

Затем получите такой параметр:

Parameters.getParameter("keyName");