Відповіді:
Ви можете мати окремий файл конфігурації, але вам доведеться читати його "вручну", він 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 серіалізувати / десеріалізувати за потребою. Ви можете назвати його тим, що хочете. Якщо ваш конфігурація "статична" і не потребує змін, ви також можете додати її до проекту як вбудований ресурс.
Сподіваюся, це дає певну ідею
ConfigurationSettings
тепер застарілий і замінений на ConfigurationManager
, тому еквівалент був би заразConfigurationManager.AppSettings
Файли конфігурації залежать від додатків, а не в межах монтажу. Тому вам потрібно буде розмістити розділи конфігурації вашої бібліотеки у файлі конфігурації кожного додатка, який використовує вашу бібліотеку.
Однак, це не дуже добра практика отримання конфігурації з файлу конфігурації програми, особливо з appSettings
розділу, в бібліотеці класів. Якщо вашій бібліотеці потрібні параметри, вони, ймовірно, повинні передаватися як аргументи методів у конструкторах, фабричних методах тощо тим, хто викликає вашу бібліотеку. Це запобігає виклику додатків від випадкового використання записів конфігурації, очікуваних бібліотекою класів.
Однак, файли конфігурації XML надзвичайно зручні, тому найкращий компроміс, який я знайшов, - це використання спеціальних розділів конфігурації. Ви можете помістити конфігурацію вашої бібліотеки у XML-файл, який автоматично зчитується та аналізується рамкою, і ви уникаєте потенційних аварій.
Ви можете дізнатися більше про розділи конфігурації на MSDN, а також про Філа Хаака є чудова стаття про них.
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 / applicatioNettings та значеннями за замовчуванням для цих налаштувань із параметрів Settings.settings. файл.
Однак цей файл конфігурації не буде використовуватися під час виконання - натомість бібліотека класів використовує файл конфігурації свого хостинг-програми.
Я вважаю, що головна причина для створення цього файлу полягає в тому, що ви можете скопіювати / вставити налаштування у файл конфігурації хост-програми.
Наразі я створюю плагіни для роздрібної торгової марки програмного забезпечення, які фактично є бібліотеками класу .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);
}
}
Зразок файлу 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;
Рішення, розміщене Yiannis Leoussis, є прийнятним, але у мене виникли певні проблеми.
По-перше, 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";