Answers:
你可以有单独的配置文件,但是您必须“手动”读取它,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"];
现在,假设我们有一个名为MyApp.exe的Windows应用程序,它引用了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上了解有关自定义配置部分的更多信息,Phil Haack对此也有不错的文章。
appSettings
,自定义部分不是基于约定的,而是一种不错的选择。毕竟,ASP.NET Membership几乎使用了什么。
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");
我目前正在为零售软件品牌创建插件,它们实际上是.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
{
.
.
.
.
}
为了回应有关装配体不能特定于项目的评论,装配体可以并且可以提供极大的灵活性,特别是。在使用IOC框架时。
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从应用程序的配置文件中获取其值。如果使用此程序集的任何应用程序缺少配置文件中的该设置,您将得到一个异常o显然有些东西丢失了。
MissingConfigFileAppSettings是自定义异常。您可能要抛出其他异常。
当然,对于这些类的方法,更好的设计是将这些值作为参数提供,而不是依赖于配置文件设置。这样,使用这些类的应用程序可以决定从何处以及如何提供这些值。
前言:我正在使用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,则每次每次汇编代码都必须重写。因此,这是我的版本,用于Class每次需要时实例化。
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";