类库的app.config


80

我看不到VS2008向导为类库生成的app.config文件。在我的研究中,我发现在一个应用程序中仅存在一个app.config。

将app.config手动添加到类库是否是一件坏事,还是在类库中有其他方法可以满足app.config的目的?

我需要将log4net配置信息存储在app.config文件中。


2
您可以从库中读取可执行项目配置文件。
Akram Shahda 2011年

Answers:


98

通常,您应该将app.config文件添加到类库项目中。如果您没有痛苦的弯曲和扭曲,就不会使用它。它根本不会伤害图书馆项目-它根本不会做任何事情。

相反,您可以配置正在使用库的应用程序。因此所需的配置信息会放在那儿。每个可能使用您的库的应用程序都有不同的要求,因此这实际上也是合乎逻辑的。


23
对你有益。不过,我没有回答您的问题。您显然拥有某种本地配置的系统,该系统不适用于在此处提出问题的人员。
Andrew Barber

1
我有一个Selenium WebDriver类库,我从NUnit运行所有我的测试用例。我宁愿不必担心在NUnit中设置配置。我该如何弯曲才能完成此任务?:-)
MacGyver 2012年

3
弄清楚了...如果使用NUnit,则将您的app.config文件命名为与* .nunit项目文件名相同的名称。因此,例如,如果您将项目命名为“ ClassLibraryA.nunit”,则将您的类库配置文件命名为“ ClassLibraryA.config”。他们还需要驻留在相同的文件夹/目录中。NUnit实际上是使用它作为主要配置文件....添加对System.Configuration的引用(在.NET选项卡中)..并使用以下代码:string settingValue = ConfigurationManager.AppSettings [“ settingName”];
MacGyver '02

2
在进行集成测试时,您如何建议进行设置?对我来说,在测试库中有一个带有连接字符串的app.config似乎是合乎逻辑的。
Tomas Jansson

2
如果由于您不拥有该应用程序而无法配置该应用程序,该怎么办。
电压峰值

50

我不知道为什么还没有给出这个答案:

通常,同一库的不同调用者将使用不同的配置。这意味着配置必须驻留在可执行应用程序中,而不是类库中。

您可以在类库项目中创建一个app.config。它将包含您在库中创建的项目的默认配置。例如,如果您在类库中创建实体框架模型,它将包含连接字符串。

但是,调用库的可执行应用程序将不会使用这些设置。而是可以将这些设置从library.dll.config文件复制到调用方的app.config或web.config中,以便可以将其更改为特定于调用方以及调用方所处的环境。部署。

从第一天开始,.NET就是这样。


2
但是,如果我需要从类库中调用webserice功能,该怎么办?VS创建了一个默认的app.config,但是尝试调用webservice函数时我的应用程序崩溃了-它找不到配置条目...
Laserson 2011年

您必须将放置在类库app.config中的元素复制到类库的调用者的app.config或web.config中。这使呼叫者可以控制配置。例如,调用者现在可以更改您的类库调用的服务的URL,而您的类库甚至都不知道该更改。
约翰·桑德斯,

6
@约翰·桑德斯:“可能需要”完全正确。因此,在某些情况下,每个服务器的配置设置可能不同(例如,连接字符串),并且让dll具有自己的配置要比为每个使用该dll的程序集大量复制它更方便。在我看来,Microsoft / .NET的首选用法并不是圣杯。实际上,这取决于在部署方案中最方便的方法。无需告诉Todd,他的观点与您或Microsoft一样重要。

我对这个解决方案非常感兴趣-对我来说听起来很理想。库具有默认设置是有意义的,而应用程序将具有覆盖默认设置的能力。您是否将扩展设置如何从库的app.config传播到执行程序集的app.config,或将我定向到相关资源?
2014年

@crush:称为“复制和粘贴”。.NET的强类型设置功能会有所帮助,因为它将默认值烘焙到程序集中。
约翰·桑德斯

42

乔恩(Jon),有很多意见没有正确回答您的问题。

我会说出我的意见,然后告诉您如何正确执行您的要求。

我看不出为什么程序集无法拥有自己的配置文件。为什么第一个原子级别(是一个真实的单词?)在应用程序级别?为什么不在解决方案级别?这是一个任意的,最好的决定,因此是一个意见。如果您要编写日志记录库并希望为其包含配置文件,那么该文件将在全球范围内使用,那么为什么不能使用内置设置功能呢?我们都做到了...试图为其他开发人员提供“强大”的功能。怎么样?通过做出固有转换为限制的假设。这正是MS使用设置框架所做的事情,因此您必须“愚弄”它。

要直接回答您的问题,只需手动添加配置文件(xml),然后将其命名为与您的库匹配并包含“ config”扩展名。例:

MyDomain.Mylibrary.dll.Config

接下来,使用ConfigurationManager加载文件和访问设置:

string assemblyPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath;
Configuration cfg = ConfigurationManager.OpenExeConfiguration(assemblyPath);
string result = cfg.AppSettings.Settings["TEST_SETTING"].Value;

请注意,即使您已明确选择应用程序配置文件,它也完全支持machine.config层次结构。换句话说,如果该设置不存在,它将解析得更高。设置还将覆盖machine.config条目。


3
-1:您的意见本身并不重要。事实很重要。从第1天开始创建.NET,以便库的调用者确定库中各项的配置。这是唯一对配置有意义的东西,因为库的不同调用者可能需要不同的配置。
约翰·桑德斯

18
@JohnSaunders“库的不同调用者可能需要不同的配置。” 确实,它们“可能”需要不同的配置,并且在所有配置确实依赖于调用方的情况下,您的逻辑都是很合理的。但是在某些情况下,配置在内部用于类库,并且无论调用者是什么,配置都是完全相同的。如果您有10个使用库的应用程序,那么将完全相同的配置复制并粘贴到10个配置文件中会变得更糟。
wired_in

3
@ToddBeaulieu:我想你想要的词是“原子性”。
nicodemus13 2014年

3
在插件体系结构中,如果所有插件都有自己的配置文件,这确实很有意义。
Davatar '16

4
@RMuesi没有人说它永远不会改变,只是它不依赖于库的调用者。Config可以更改,具体取决于您是调试库还是生产版本。它可能会根据您要构建的环境等而更改。
wired_in

6

实际上,您正在实现的类库正在从正在使用它的应用程序内部的app.config中检索信息,因此,在VS.net中实现类库配置的最正确方法是在NET中准备app.config。应用程序来配置它消耗的所有内容,例如库配置。

我在log4net上做了一些工作,发现准备该应用程序的人总是在main app.config中有一个log4net配置部分。

我希望这个信息对您有所帮助。

待会见,并发表有关找到的解决方案的评论。

编辑:

在下一个链接中,您具有带有log4net部分的app.config

http://weblogs.asp.net/tgraham/archive/2007/03/15/a-realistic-log4net-config.aspx


2
+1正好;在app.config从实际的程序加载的最终运行......而不是个人的类库。坦率地说,有多少人不知道这个非常基本的事实,这令人有些困惑。
Andrew Barber

也许人们来自Java语言,在那里您有一个log4java.properties和用于应用程序的单独的属性文件。
Amedio

6

如果要在使用类库的同时使用log4Net配置项目日志记录,则实际上不需要任何配置文件。您可以在一个类中配置log4net记录器,并且可以将该类用作库。

由于log4net提供了配置它的所有选项。

请在下面找到代码。

public static void SetLogger(string pathName, string pattern)
        {
            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = pattern;
            patternLayout.ActivateOptions();

            RollingFileAppender roller = new RollingFileAppender();
            roller.AppendToFile = false;
            roller.File = pathName;
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.MaximumFileSize = "1GB";
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            MemoryAppender memory = new MemoryAppender();
            memory.ActivateOptions();
            hierarchy.Root.AddAppender(memory);

            hierarchy.Root.Level = log4net.Core.Level.Info;
            hierarchy.Configured = true;
      }

现在,您无需调用XmlConfigurator.Configure(new FileInfo(“ app.config”)),就可以直接使用所需的路径和模式调用SetLogger,以在Global.asax应用程序启动功能中设置记录器。

并使用以下代码记录错误。

        public static void getLog(string className, string message)
        {
            log4net.ILog iLOG = LogManager.GetLogger(className);
            iLOG.Error(message);    // Info, Fatal, Warn, Debug
        }

通过使用以下代码,您无需在应用程序web.config中或库的app.config内都无需写一行。


2
我觉得这是最好的答案...而不是讨论是否应允许库使用配置文件...此答案回答了OP使用Log4net的问题
saurav

1
尽管该问题以log4net为例,但实际的问题通常与配置有关。我会说关于log4net的答案实际上是不相关的。
宾基

4

实际上,在极少数情况下,您可以将app.config存储在类库中(通过手动添加),然后通过OpenExeConfiguration对其进行解析

 var fileMap =
    new ExeConfigurationFileMap {ExeConfigFilename = 
    @"C:\..somePath..\someName.config"};
 System.Configuration.Configuration config =
    ConfigurationManager.OpenMappedExeConfiguration(fileMap, 
    ConfigurationUserLevel.None);

您应该真正估算出此需求。对于抽象数据,它不是最佳解决方案,但是“配置节”可能非常有用!

例如,我们仅使用基于Channel Factory T的Unity容器和Injection Factory,就组织了没有任何元数据的解耦的N层WCF体系结构。从clientsection读取端点,并轻松地在一个地方添加/更改它们。


3

如果使用跟踪器/记录器,则确实要将App.config添加到测试类库中。否则,通过测试运行程序(例如TestDriven.Net)运行测试时,不会记录任何内容

例如,我TraceSource在程序中使用,但是运行测试不会记录任何内容,除非我还将带有跟踪/日志配置的App.config文件也添加到测试类库中。

否则,将App.config添加到类库不会执行任何操作。


2

对于非手动创建app.config的答案是Visual Studio项目“属性/设置”选项卡。

添加设置并保存后,将自动创建app.config。此时,将在{ yourclasslibrary .Properties }命名空间中生成一堆代码,其中包含与您的设置相对应的属性。这些设置本身将放置在app.config的applicationSettings设置中。

 <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="ClassLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<applicationSettings>
    <ClassLibrary.Properties.Settings>
        <setting name="Setting1" serializeAs="String">
            <value>3</value>
        </setting>
    </BookOneGenerator.Properties.Settings>
</applicationSettings>

如果添加了一个名为Setting1 = 3的应用程序范围设置,则将创建一个名为Setting1的属性。这些属性已成为二进制文件的编译部分,并用DefaultSettingValueAttribute装饰,该属性设置为在开发时指定的值。

     [ApplicationScopedSetting]
    [DebuggerNonUserCode]
    [DefaultSettingValue("3")]
    public string Setting1
    {
        get
        {
            return (string)this["Setting1"];
        }
    }

因此,如在类库代码中一样,如果运行时配置文件中不存在相应的设置,则您将利用这些属性,它将回退以使用默认值。这样一来,应用程序就不会因为缺少设置项而崩溃,这在您不知道这些工作原理时第一次使您非常困惑。现在,您在问自己如何在已部署的库中指定我们自己的新值,并避免使用默认设置值?

当我们正确配置可执行文件的app.config时,就会发生这种情况。两步。1.我们意识到我们将为该类库提供一个设置部分,并且2.进行了少量修改后,将类库的配置文件粘贴到了可执行文件config中。(有一种方法可以将类库配置文件保留在外部,而您只需从可执行文件的配置中引用它即可。

因此,您可以为类库提供一个app.config,但是如果您未将其与父应用程序正确集成,则它是无用的。看到这里我前一段时间写的:链接


1

将类库项目添加到解决方案时,不会自动添加app.config文件。

据我所知,没有相反的迹象表明这样做是手动的。我认为这是一种常见用法。

关于log4Net config,您不必将配置放入app.config中,您可以在项目中同时拥有一个专用的conf文件以及一个app.config文件。

此链接http://logging.apache.org/log4net/release/manual/configuration.html将为您提供有关这两种方法的示例(app.config和独立的log4net conf文件中的部分)


app.config向库项目添加不会造成任何伤害,不。但是它们都不会被使用。
Andrew Barber

1
@AndrewBarber它将在测试项目中使用。请参阅stackoverflow.com/a/31389495
Binki

0

我建议使用Properties.Settings在类库中存储诸如ConnectionStrings之类的值。例如,当您尝试添加表适配器时,Visual Studio的建议将所有连接字符串存储在此处。 在此处输入图片说明

然后,可以通过在clas库中的每个位置使用此代码来访问它们

var cs=  Properties.Settings.Default.[<name of defined setting>];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.