Ответы:
Вы можете иметь отдельный файл конфигурации, но вам придется читать его «вручную», он 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.
Выше приведен базовый пример кода, для тех, кто заинтересован в полномасштабном примере, пожалуйста, обратитесь к этому другому ответу .
К сожалению, вы можете иметь только один файл 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 по мере необходимости. Вы можете называть это как хотите. Если ваш конфиг "статический" и не нуждается в изменении, вы также можете добавить его в проект в качестве встроенного ресурса.
Надеюсь, что это дает некоторую идею
ConfigurationSettings
в настоящее время устарела и заменена на ConfigurationManager
, так что эквивалент будет теперьConfigurationManager.AppSettings
Конфигурационные файлы находятся в области приложения, а не в области сборки. Поэтому вам нужно поместить разделы конфигурации вашей библиотеки в файл конфигурации каждого приложения, которое использует вашу библиотеку.
Тем не менее, не рекомендуется получать конфигурацию из файла конфигурации приложения, особенно из appSettings
раздела, в библиотеке классов. Если вашей библиотеке нужны параметры, они, вероятно, должны быть переданы как аргументы метода в конструкторах, фабричных методах и т. Д. Тем, кто вызывает вашу библиотеку. Это предотвращает случайное повторное использование вызывающими приложениями записей конфигурации, ожидаемых библиотекой классов.
Тем не менее, файлы конфигурации XML чрезвычайно удобны, поэтому лучший компромисс, который я нашел, это использование пользовательских разделов конфигурации. Вы можете поместить конфигурацию вашей библиотеки в XML-файл, который автоматически читается и анализируется платформой, и вы избегаете возможных аварий.
Вы можете узнать больше о пользовательских разделах конфигурации на MSDN, а также у Phil Haack есть хорошая статья о них.
appSettings
пользовательских разделов предлагается отличная альтернатива; это в значительной степени то, что использует членство ASP.NET в конце концов.
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 (Свойства проекта, Настройки), он добавит в ваш проект файл app.config с соответствующими разделами userSettings / applicationatioNSettings, а также значения по умолчанию для этих настроек из вашего Settings.settings. файл.
Однако этот файл конфигурации не будет использоваться во время выполнения - вместо этого библиотека классов использует файл конфигурации своего хост-приложения.
Я считаю, что основная причина создания этого файла заключается в том, что вы можете скопировать / вставить настройки в файл конфигурации хост-приложения.
В настоящее время я создаю плагины для розничной торговой марки программного обеспечения, которые на самом деле являются библиотеками классов .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
В ответ на первоначальный вопрос я обычно добавляю файл конфигурации в свой тестовый проект в виде ссылки; затем вы можете использовать атрибут DeploymentItem, чтобы добавить его в папку Out тестового прогона.
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
В ответ на комментарии о том, что сборки не могут быть конкретными для проекта, они могут, и это обеспечивает большую гибкость, особенно. при работе с фреймворками МОК.
Я столкнулся с той же проблемой и решил ее, создав статический класс 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");
сборки не имеют своего собственного файла 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 является пользовательским исключением. Вы можете бросить другое исключение.
Конечно, лучше было бы, чтобы метод этих классов предоставлял эти значения в качестве параметров, а не полагался на настройку файла конфигурации. Таким образом, приложения, использующие эти классы, могут решить, откуда и как они предоставляют эти значения.
Преамбула : я использую 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");
Насколько я знаю, вы должны скопировать + вставить нужные разделы из библиотеки .config в файл .config приложений. Вы получаете только 1 app.config на исполняемый экземпляр.
Почему бы не использовать:
[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
string exeConfigPath = this.GetType().Assembly.Location;
что-то вроде:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";