Czy istnieje odpowiednik app.config
dla bibliotek (DLL)? Jeśli nie, jaki jest najłatwiejszy sposób przechowywania ustawień konfiguracji specyficznych dla biblioteki? Proszę wziąć pod uwagę, że biblioteka może być używana w różnych aplikacjach.
Czy istnieje odpowiednik app.config
dla bibliotek (DLL)? Jeśli nie, jaki jest najłatwiejszy sposób przechowywania ustawień konfiguracji specyficznych dla biblioteki? Proszę wziąć pod uwagę, że biblioteka może być używana w różnych aplikacjach.
Odpowiedzi:
Państwo może mieć osobny plik konfiguracyjny, ale musisz ją przeczytać „ręcznie”, to ConfigurationManager.AppSettings["key"]
będzie tylko do odczytu config Zgromadzenia uruchomiony.
Zakładając, że używasz Visual Studio jako swojego IDE, możesz kliknąć prawym przyciskiem myszy żądany projekt → Dodaj → Nowy element → Plik konfiguracji aplikacji
Spowoduje to dodanie App.config
do folderu projektu, umieszczenie ustawień tam w <appSettings>
sekcji. Jeśli nie używasz programu Visual Studio i dodajesz plik ręcznie, nadaj mu nazwę: DllName.dll.config , w przeciwnym razie poniższy kod nie będzie działał poprawnie.
Teraz do odczytu z tego pliku mamy taką funkcję:
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;
}
I aby z niego skorzystać:
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");
...
}
Będziesz także musiał dodać odwołanie do przestrzeni nazw System.Configuration, aby klasa ConfigurationManager była dostępna.
Podczas budowania projektu, oprócz biblioteki DLL, będziesz również mieć DllName.dll.config
plik, jest to plik, który musisz opublikować z samą biblioteką DLL.
Powyższy kod to podstawowy przykładowy kod. Osoby zainteresowane pełnym przykładem mogą skorzystać z innej odpowiedzi .
Niestety, możesz mieć tylko jeden plik app.config na plik wykonywalny, więc jeśli masz bibliotekę DLL połączoną z aplikacją, nie mogą one mieć własnych plików app.config.
Rozwiązanie:
nie musisz umieszczać pliku App.config w projekcie biblioteki klas.
Umieszczasz plik App.config w aplikacji, która odwołuje się do biblioteki dll biblioteki klas.
Na przykład, powiedzmy, że mamy bibliotekę klas o nazwie MyClasses.dll, która używa pliku app.config w następujący sposób:
string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];
Załóżmy teraz, że mamy aplikację Windows o nazwie MyApp.exe, która odwołuje się do MyClasses.dll. Zawierałby plik App.config z wpisem takim jak:
<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>
LUB
Plik xml jest najlepszym odpowiednikiem pliku app.config. W razie potrzeby użyj serializacji / deserializacji XML. Możesz to nazwać, jak chcesz. Jeśli Twoja konfiguracja jest „statyczna” i nie wymaga zmian, możesz również dodać ją do projektu jako zasób osadzony.
Mam nadzieję, że to daje jakiś pomysł
ConfigurationSettings
jest teraz przestarzały i zastąpiony przez ConfigurationManager
, więc odpowiednik byłby terazConfigurationManager.AppSettings
Pliki konfiguracyjne mają zakres aplikacji, a nie zakres zestawu. Musisz więc umieścić sekcje konfiguracyjne swojej biblioteki w pliku konfiguracyjnym każdej aplikacji, która korzysta z Twojej biblioteki.
To powiedziawszy, nie jest dobrą praktyką pobieranie konfiguracji z pliku konfiguracyjnego aplikacji, szczególnie z appSettings
sekcji, w bibliotece klas. Jeśli twoja biblioteka potrzebuje parametrów, prawdopodobnie powinny one być przekazywane jako argumenty metod w konstruktorach, metodach fabrycznych itp. Przez tego, kto wywołuje twoją bibliotekę. Zapobiega to przypadkowemu używaniu przez wywołujące aplikacje pozycji konfiguracji, które były oczekiwane przez bibliotekę klas.
To powiedziawszy, pliki konfiguracyjne XML są niezwykle przydatne, więc najlepszym kompromisem, jaki znalazłem, jest użycie niestandardowych sekcji konfiguracji. Możesz umieścić konfigurację swojej biblioteki w pliku XML, który jest automatycznie odczytywany i analizowany przez framework i unikasz potencjalnych wypadków.
Możesz dowiedzieć się więcej o sekcjach konfiguracji niestandardowej w MSDN, a także Phil Haack ma na ich temat fajny artykuł .
appSettings
sekcje niestandardowe stanowią doskonałą alternatywę; w końcu jest to właściwie to, czego używa członkostwo 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
}
Żeby coś zrobić, przerobiłem pierwszą odpowiedź na klasę. Użycie jest takie jak:
ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
Jeśli dodasz ustawienia do projektu biblioteki klas w programie Visual Studio (właściwości projektu, ustawienia), doda on plik app.config do projektu z odpowiednimi sekcjami userSettings / applatioNSettings i domyślnymi wartościami tych ustawień z ustawień. plik.
Jednak ten plik konfiguracyjny nie będzie używany w czasie wykonywania - zamiast tego biblioteka klas używa pliku konfiguracyjnego swojej aplikacji hostującej.
Uważam, że głównym powodem generowania tego pliku jest to, że można skopiować / wkleić ustawienia do pliku konfiguracyjnego aplikacji hosta.
Obecnie tworzę wtyczki dla marki oprogramowania detalicznego, które są w rzeczywistości bibliotekami klasy .net. Zgodnie z wymaganiami każda wtyczka musi być skonfigurowana przy użyciu pliku konfiguracyjnego. Po kilku badaniach i testach skompilowałem następującą klasę. Wykonuje swoją pracę bez zarzutu. Zauważ, że nie zaimplementowałem lokalnej obsługi wyjątków w moim przypadku, ponieważ łapię wyjątki na wyższym poziomie.
Może być konieczne wprowadzenie pewnych poprawek, aby uzyskać właściwy przecinek dziesiętny, w przypadku liczb dziesiętnych i podwójnych, ale działa to dobrze w przypadku moich informacji o kulturze ...
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);
}
}
Przykład pliku App.Config
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Stosowanie:
somebooleanvar = Settings.Setting<bool>("Enabled");
somestringlvar = Settings.Setting<string>("ExportPath");
someintvar = Settings.Setting<int>("Seconds");
somedoublevar = Settings.Setting<double>("Ratio");
Kredyty dla Shadow Wizard i MattC
Odpowiadając na pierwotne pytanie, zazwyczaj dodaję plik konfiguracyjny do mojego projektu testowego jako łącze; można następnie użyć atrybutu DeploymentItem, aby dodać go do folderu Out przebiegu testowego.
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
W odpowiedzi na komentarze, że zestawy nie mogą być specyficzne dla projektu, mogą i zapewnia to dużą elastyczność, szczególnie. podczas pracy z frameworkami IOC.
Napotkałem ten sam problem i rozwiązałem go, tworząc klasę statyczną Parameters
po dodaniu pliku konfiguracyjnego aplikacji do projektu:
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;
}
}
Następnie uzyskaj parametr taki jak ten:
Parameters.GetParameter("keyName");
zestawy nie mają własnego pliku app.config. Używają pliku app.config aplikacji, która ich używa. Więc jeśli twój zestaw oczekuje pewnych rzeczy w pliku konfiguracyjnym, po prostu upewnij się, że plik konfiguracyjny twojej aplikacji zawiera te wpisy.
Jeśli zestaw jest używany przez wiele aplikacji, każda z tych aplikacji będzie musiała mieć te wpisy w swoim pliku app.config.
To, co poleciłbym, to na przykład zdefiniowanie właściwości klas w twoim zestawie dla tych wartości
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;
}
}
Tutaj właściwość ExternalServicesUrl pobiera swoją wartość z pliku konfiguracyjnego aplikacji. Jeśli w którejkolwiek aplikacji używającej tego zestawu brakuje tego ustawienia w pliku konfiguracyjnym, pojawi się wyjątek o jasne jest, że czegoś brakuje.
MissingConfigFileAppSettings to niestandardowy wyjątek. Możesz zgłosić inny wyjątek.
Oczywiście lepszym rozwiązaniem byłoby zapewnienie metody tych klas jako parametrów, a nie poleganie na ustawieniach pliku konfiguracyjnego. W ten sposób aplikacje korzystające z tych klas mogą decydować, skąd i jak dostarczają te wartości.
Preambuła : używam NET 2.0;
Rozwiązanie przesłane przez Yiannisa Leoussisa jest do zaakceptowania, ale miałem z nim pewien problem.
Po pierwsze, static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
zwraca null. Musiałem to zmienić nastatic AppSettingSection = myDllConfig.AppSettings;
Wtedy return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
nie ma haczyka na wyjątki. Więc zmieniłem to
try
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
return default(T);
}
Działa to bardzo dobrze, ale jeśli masz inną bibliotekę dll, za każdym razem musisz przepisać kod dla każdego zestawu. Tak więc to jest moja wersja dla klasy do tworzenia instancji za każdym razem, gdy potrzebujesz.
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);
}
}
}
W przypadku konfiguracji:
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Użyj go jako:
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");
O ile wiem, musisz skopiować i wkleić żądane sekcje z biblioteki .config do pliku .config aplikacji. Otrzymujesz tylko 1 plik app.config na instancję wykonywalną.
Dlaczego nie użyć:
[ProjectNamespace].Properties.Settings.Default.[KeyProperty]
dla C #My.Settings.[KeyProperty]
dla VB.NETWystarczy wizualnie zaktualizować te właściwości w czasie projektowania poprzez:
[Solution Project]->Properties->Settings
użycie z konfiguracji musi być bardzo łatwe w następujący sposób:
var config = new MiniConfig("setting.conf");
config.AddOrUpdate("port", "1580");
if (config.TryGet("port", out int port)) // if config exist
{
Console.Write(port);
}
aby uzyskać więcej informacji, zobacz MiniConfig
string exeConfigPath = this.GetType().Assembly.Location;
na coś takiego:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";