相当于库的“app.config”(DLL)

问题描述 投票:134回答:14

是否有相当于app.config的库(DLL)?如果不是,存储特定于库的配置设置的最简单方法是什么?请考虑该库可能在​​不同的应用程序中使用。

c# .net dll settings app-config
14个回答
151
投票

您可以拥有单独的配置文件,但是您必须“手动”读取它,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
投票

使用添加现有项目,从dll项目中选择应用程序配置。在单击添加之前,使用添加按钮右侧的小向下箭头“添加为链接”

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


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");

0
投票

据我所知,你必须将你想要的部分从库.config复制+粘贴到应用程序.config文件中。每个可执行实例只能获得1个app.config。


0
投票

为什么不使用:

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

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

[Solution Project]->Properties->Settings


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


28
投票

不幸的是,每个可执行文件只能有一个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。你可以随心所欲地称呼它。如果您的配置是“静态的”并且不需要更改,您还可以将其作为嵌入式资源添加到项目中。

希望它能给出一些想法


9
投票

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

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

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

您可以在MSDN以及Phil Haack has a nice article上了解有关自定义配置部分的更多信息。


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
投票

如果将设置添加到Visual Studio中的类库项目(项目属性,设置),它将使用相关的userSettings / applicatioNSettings部分将app.config文件添加到项目中,并使用Settings.settings中的这些设置的默认值。文件。

但是,此配置文件不会在运行时使用 - 而是类库使用其托管应用程序的配置文件。

我相信生成此文件的主要原因是您可以将设置复制/粘贴到主机应用程序的配置文件中。


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和MattC的致谢


2
投票

在回答原始问题时,我通常会在我的测试项目中添加配置文件作为链接;然后,您可以使用DeploymentItem属性添加到测试运行的Out文件夹中。

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

为了回应Assemblies不能针对项目特定的评论,他们可以并且它提供了极大的灵活性。在使用IOC框架时。


2
投票

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

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是一个自定义异常。您可能想要抛出不同的异常。

当然,更好的设计是将这些类的方法作为参数提供,而不是依赖于配置文件设置。这样,使用这些类的应用程序可以决定它们提供这些值的位置和方式。

© www.soinside.com 2019 - 2024. All rights reserved.