等效于库的“ app.config”(DLL)

对于库(DLL) ,是否有等价于 app.config的代码?如果没有,存储特定于库的配置设置的最简单方法是什么?请考虑该库可能用于不同的应用程序。

177949 次浏览

据我所知,您必须从库中复制并粘贴所需的部分。配置到应用程序中。配置文件。每个可执行实例只能得到1个 app.config。

程序集没有自己的 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 是一个自定义异常。您可能希望引发其他异常。

当然,更好的设计是将这些类的方法作为参数提供,而不是依赖于配置文件设置。这样,使用这些类的应用程序就可以决定从何处以及如何提供这些值。

配置文件是应用程序范围的,而不是程序集范围的。因此,您需要将库的配置部分放在使用库的每个应用程序的配置文件中。

也就是说,从类库中的应用程序配置文件(特别是 appSettings部分)获取配置并不是一个好的做法。如果您的库需要参数,那么调用您的库的任何人都应该将它们作为构造函数、工厂方法等中的方法参数传递。这可以防止调用应用程序意外地重用类库所期望的配置项。

也就是说,XML 配置文件非常方便,因此我发现最好的折衷方案是使用自定义配置部分。您可以将库的配置放在一个 XML 文件中,该文件由框架自动读取和解析,从而避免了潜在的事故。

您可以在 MSDN菲尔 · 哈克有篇好文章上了解更多关于自定义配置部分的信息。

如果您将 Settings 添加到 Visual Studio 中的 Class Library 项目(项目属性,设置) ,它将向您的项目添加一个 app.config 文件,其中包含相关的 userSettings/applicatioNSettings 部分,以及来自 Settings.sets 文件的这些设置的默认值。

但是这个配置文件不会在运行时使用,而是类库使用宿主应用程序的配置文件。

我相信生成这个文件的主要原因是为了将设置复制/粘贴到宿主应用程序的配置文件中。

您的 可以有单独的配置文件,但是您必须“手动”读取它,ConfigurationManager.AppSettings["key"]将只读取正在运行的程序集的配置。

假设您使用 Visual Studio 作为 IDE,您可以右键单击所需的项目→添加→新项→应用程序配置文件

这将添加 App.config到项目文件夹,把你的设置在那里的 <appSettings>节。如果您没有使用 VisualStudio 手动添加文件,请确保将其命名为: 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 本身发布的文件。

在 VS 项目中,您应该将. config 文件“ Copy to output directory”设置为“ Always Copy”。

以上是基本的示例代码,对于那些感兴趣的全尺寸示例,请参考 另一个答案

不幸的是,每个可执行文件只能有一个 app.config 文件,因此如果将 DLL 链接到应用程序中,它们就不能有自己的 app.config 文件。

解决办法是: 您不需要将 App.config 文件放在 Class Library 的项目中。
将 App.config 文件放入引用您的类的应用程序中 图书馆的 DLL。

例如,假设我们有一个名为 MyClasses.dll 的类库 像这样使用 app.config 文件:

string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];

现在,假设我们有一个名为 MyApp.exe 的 Windows 应用程序 它将包含一个 App.config,其中包含一个如下条目 作为:

<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>

或者

Xml 文件最好等效于 app.config 如果你的配置是“静态的”,那么你可以随心所欲的称呼它 并且不需要更改,您也可以将其作为 嵌入式资源。

希望能给你点灵感

使用添加现有项,从 dll 项目中选择 app 配置。在单击 add 之前,使用 add 按钮右侧的小向下箭头来“ add as link”

我在我的开发中一直这样做。

对于最初的问题,我通常将配置文件作为链接添加到测试项目中; 然后可以使用 DeploymentItem 属性将其添加到测试运行的 Out 文件夹中。

[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}

有人认为程序集不可能是特定于项目的,但是它们可以,而且它提供了很大的灵活性。在使用 IOC 框架时。

我目前正在创建一个零售软件品牌的插件,这实际上是。网络类库。根据需要,每个插件都需要使用一个配置文件进行配置。经过一些研究和测试,我编译了以下类。它完美地完成了任务。请注意,在我的例子中,我没有实现本地异常处理,因为我在更高的级别捕获异常。

可能需要做一些调整以获得正确的小数点,以防小数和双精度数,但它对我的 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");

阴影向导和马特 C 的学分

前言 : 我使用的是 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");
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");

我遇到了同样的问题,在向项目中添加应用程序配置文件后,通过创建一个静态类 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");

为什么不使用:

  • C # 的 [ProjectNamespace].Properties.Settings.Default.[KeyProperty]
  • 用于 VB.NET 的 My.Settings.[KeyProperty]

您只需在设计时通过以下方法直观地更新这些属性:

[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

我看了一下 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");
}
}
}

上述工作的几个答案 如果使用 暗影巫师 然后替换

string exeConfigPath = this.GetType().Assembly.Location;

string exeConfigPath = typeof(MyClassName).Assembly.Location;

如果使用 < a href = “ https://stackoverflow. com/users/2478456/yiannis-leoussis”> yiannis-leoussis (至少在 Windows 上)更换

static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);

使用 LocalPath

static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Uri.LocalPath);