Эквивалент «app.config» для библиотеки (DLL) - PullRequest
138 голосов
/ 04 марта 2011

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

Ответы [ 14 ]

150 голосов
/ 04 марта 2011

Вы можете иметь отдельный файл конфигурации, но вам придется читать его "вручную", 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.

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

27 голосов
/ 04 марта 2011

К сожалению, вы можете иметь только один файл 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.Вы можете называть это как хотите.Если ваш конфиг "статический" и не нуждается в изменении, вы также можете добавить его в проект в качестве встроенного ресурса.

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

9 голосов
/ 04 марта 2011

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

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

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

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

5 голосов
/ 02 февраля 2017
public class ConfigMan
{
    #region Members

    string _assemblyLocation;
    Configuration _configuration;

    #endregion Members

    #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 Constructors

    #region Properties

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

    #endregion Properties

    #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 Methods
}

Просто для того, чтобы чем-то заняться, я реорганизовал лучший ответ в классе. Использование что-то вроде:

ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
3 голосов
/ 11 февраля 2015

В настоящее время я создаю плагины для розничной торговой марки программного обеспечения, которые на самом деле являются библиотеками классов .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");

Кредиты для Shadow Wizard & MattC

3 голосов
/ 04 марта 2011

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

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

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

2 голосов
/ 03 февраля 2017

Я столкнулся с той же проблемой и решил ее, создав статический класс 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");
2 голосов
/ 30 мая 2013

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

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

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

1 голос
/ 17 декабря 2015

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

Решение, опубликованное Яннис Леуссис , приемлемо, но у меня возникли некоторые проблемы с ним.

Сначала static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); возвращает ноль.Мне пришлось изменить его на static AppSettingSection = myDllConfig.AppSettings;

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

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");
1 голос
/ 17 мая 2013

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

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

...