Эквивалент приложение.config ' для библиотеки (DLL)


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

14 124

14 ответов:

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

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

добавить App.config в папку проекта, поместите свои настройки там под . Если вы не используете Visual Studio и не добавляете файл вручную, обязательно дайте ему такое имя:DllName.файл DLL.конфигурации, иначе код не будет работать должным образом.

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

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.Пространство имен конфигурации для того, чтобы класс ConfigurationManager был доступен.

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

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

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

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

например, предположим, что у нас есть библиотека классов с именем MyClasses.dll, которая использует приложение.конфигурационный файл вот так:

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

теперь, скажем, у нас есть приложение для Windows с именем MyApp.exe, которые ссылки MyClasses.файл DLL. Он будет содержать приложение.конфиг с записью такой как:

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

или

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

надеюсь, что это дает некоторое представление

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

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

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

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

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

Если вы добавляете параметры в проект библиотеки классов в Visual Studio (свойства проекта, параметры), он добавит приложение.файл конфигурации для вашего проекта с соответствующими разделами userSettings/applicatioNSettings и значениями по умолчанию для этих параметров из Ваших настроек.файл настроек.

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

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

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

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

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

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

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

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

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

MissingConfigFileAppSettings является пользовательским исключением. Вы можете создать другое исключение.

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

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

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

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

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

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

приложение.Пример файла конфигурации

<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

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

решение опубликовано Яннис 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");

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

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

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

почему бы не использовать:

  • [ProjectNamespace].Properties.Settings.Default.[KeyProperty] для C#
  • My.Settings.[KeyProperty] для VB.NET

вам просто нужно визуально обновить эти свойства во время разработки через:

[Solution Project]->Properties->Settings

использование из конфигураций должно быть очень легко, как это:

var config = new MiniConfig("setting.conf");

config.AddOrUpdate("port", "1580");

if (config.TryGet("port", out int port)) // if config exist
{
    Console.Write(port);
}

Подробнее см. MiniConfig