库(DLL)是否等同于app.config
?如果不是,存储特定于库的配置设置的最简单方法是什么?请考虑该库可能在不同的应用程序中使用。
答案 0 :(得分:146)
您可以拥有单独的配置文件,但您必须“手动”阅读,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本身发布的文件。
以上是基本示例代码,对于那些对全尺寸示例感兴趣的人,请参阅this other answer。
答案 1 :(得分:26)
不幸的是,每个可执行文件只能有一个app.config文件,所以如果你的DLL链接到你的应用程序,他们就不能拥有自己的app.config文件。
解决方案是: 您不需要将App.config文件放在类库的项目中 您将App.config文件放在引用您的类的应用程序中 图书馆的dll。
例如,假设我们有一个名为MyClasses.dll的类库 像这样使用app.config文件:
string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];
现在,假设我们有一个名为MyApp.exe的Windows应用程序 引用MyClasses.dll。它将包含一个带有条目的App.config 为:
<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>
或强>
xml文件最适合app.config。使用xml serialize / deserialize as 需要。你可以随心所欲地称呼它。如果你的配置是“静态的” 并且不需要更改,您也可以将其添加到项目中 嵌入式资源。
希望它能给出一些想法
答案 2 :(得分:8)
配置文件是应用程序范围的,而不是程序集范围的。因此,您需要将库的配置部分放在使用您的库的每个应用程序的配置文件中。
也就是说,从类应用程序的配置文件(特别是appSettings
部分)中获取配置并不是一个好习惯。如果您的库需要参数,那么它们应该作为方法参数在构造函数,工厂方法等中传递给任何调用库的人。这可以防止调用应用程序意外重用类库所期望的配置条目。
也就是说,XML配置文件非常方便,所以我发现最好的折衷方案是使用自定义配置部分。您可以将库的配置放在XML文件中,该文件由框架自动读取和解析,您可以避免潜在的事故。
您可以在MSDN以及Phil Haack has a nice article上了解有关自定义配置部分的详情。
答案 3 :(得分:5)
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");
答案 4 :(得分:3)
如果您将设置添加到Visual Studio中的类库项目(项目属性,设置),它将使用相关的userSettings / applicatioNSettings部分将app.config文件添加到您的项目中,并将这些设置的默认值添加到您的项目中Settings.settings文件。
但是,此配置文件不会在运行时使用 - 而是类库使用其托管应用程序的配置文件。
我认为生成此文件的主要原因是您可以将设置复制/粘贴到主机应用程序的配置文件中。
答案 5 :(得分:3)
我目前正在为零售软件品牌创建插件,这些插件实际上是.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&amp; MattC
答案 6 :(得分:2)
在回答原始问题时,我通常会在测试项目中添加配置文件作为链接;然后,您可以使用DeploymentItem属性添加到测试运行的Out文件夹中。
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
作为对Assemblies不能针对项目的评论的回应,他们可以并且它提供了极大的灵活性。在使用IOC框架时。
答案 7 :(得分:1)
程序集没有自己的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从应用程序的配置文件中获取其值。如果使用此程序集的任何应用程序缺少配置文件中的该设置,您将获得异常o显然缺少某些内容。
MissingConfigFileAppSettings是一个自定义异常。你可能想要抛出一个不同的例外。
当然,更好的设计是将这些类的方法作为参数提供,而不是依赖于配置文件设置。这样,使用这些类的应用程序可以决定它们提供这些值的位置和方式。
答案 8 :(得分:1)
使用添加现有项目,从dll项目中选择应用程序配置。在单击添加之前,使用添加按钮右侧的小向下箭头“添加为链接”
我一直在我的开发中这样做。
答案 9 :(得分:1)
序言:我使用的是.NET 2.0;
Yiannis Leoussis发布的解决方案是可以接受的,但我遇到了一些问题。
首先,static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
返回null。我不得不将其更改为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");
答案 10 :(得分:1)
我遇到了同样的问题,并在向项目添加应用程序配置文件后创建了一个静态类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");
答案 11 :(得分:0)
据我所知,您必须将库中.config所需的部分复制+粘贴到应用程序.config文件中。每个可执行实例只能获得1个app.config。
答案 12 :(得分:0)
为什么不使用:
[ProjectNamespace].Properties.Settings.Default.[KeyProperty]
代表C#My.Settings.[KeyProperty]
for VB.NET 您只需在设计时通过以下方式直观地更新这些属性:
[Solution Project]->Properties->Settings
答案 13 :(得分:0)
使用配置必须非常简单,像这样:
var config = new MiniConfig("setting.conf");
config.AddOrUpdate("port", "1580");
if (config.TryGet("port", out int port)) // if config exist
{
Console.Write(port);
}
有关更多详细信息,请参见MiniConfig
答案 14 :(得分:0)
我查看了AppDomain
而不是程序集。这具有在库的静态方法中工作的好处。链接似乎可以很好地获得键值,如此处其他答案所建议的那样。
public class DLLConfig
{
public static string GetSettingByKey(AppDomain currentDomain, string configName, string key)
{
string value = string.Empty;
try
{
string exeConfigPath = (currentDomain.RelativeSearchPath ?? currentDomain.BaseDirectory) + "\\" + configName;
if (File.Exists(exeConfigPath))
{
using (Stream stream = File.OpenRead(exeConfigPath))
{
XDocument xdoc = XDocument.Load(stream);
XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == key);
value = element.Attribute("value").Value;
}
}
}
catch (Exception ex)
{
}
return value;
}
}
像这样在您的库类中使用它;
namespace ProjectName
{
public class ClassName
{
public static string SomeStaticMethod()
{
string value = DLLConfig.GetSettingByKey(AppDomain.CurrentDomain,"ProjectName.dll.config", "keyname");
}
}
}