类库的 app.config

Posted

技术标签:

【中文标题】类库的 app.config【英文标题】:app.config for a class library 【发布时间】:2011-08-06 04:59:20 【问题描述】:

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

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

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

【问题讨论】:

你可以从你的库中读取你的可执行项目配置文件。 【参考方案1】:

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

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

【讨论】:

对你有好处。不过,我没有回答你的问题。您显然有某种本土配置系统,不适用于此处提出问题的人。 我有一个 Selenium WebDriver 类库,我从 NUnit 为我的所有测试用例运行它。我宁愿不必担心在 NUnit 中设置配置。我怎样才能弯曲和扭转来完成这项工作? :-) 想通了...如果使用 NUnit,请将您的 app.config 文件命名为与 *.nunit 项目文件名相同的名称。例如,如果您将项目命名为“ClassLibraryA.nunit”,则将您的类库配置文件命名为“ClassLibraryA.config”。它们还需要驻留在同一文件夹/目录中。 NUnit 实际上使用它作为主要配置文件 .... 添加对 System.Configuration 的引用(在 .NET 选项卡中)...并使用此代码: string settingValue = ConfigurationManager.AppSettings["settingName"];跨度> 在进行集成测试时,您建议如何设置?对我来说,在带有连接字符串的测试库中有一个 app.config 似乎是合乎逻辑的。 如果由于您不拥有应用程序而无法配置应用程序怎么办。【参考方案2】:

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

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

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

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

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

【讨论】:

但是如果我需要从类库中调用 webserice 功能该怎么办? VS 创建了一个默认的 app.config 但我的应用程序在尝试调用 webservice 函数时崩溃了 - 它找不到配置条目... 您必须将放置在类库app.config中的元素复制到类库调用者的app.config或web.config中。这允许调用者控制配置。例如,调用者现在可以更改您的类库调用的服务的 URL,而您的类库甚至不会知道更改。 @John Saunders:“可能需要”是完全正确的词。因此,可能存在配置设置仅因服务器而异的情况(例如连接字符串),让 dll 拥有自己的配置比为每个使用 dll 的程序集复制很多次更方便。在我看来,Microsofts/.NET 的首选用法并不是一个圣杯。这实际上取决于部署场景中最方便的方式。无需告诉托德,他的意见与您或微软的意见一样重要。 我对这个解决方案非常感兴趣 - 这对我来说听起来很理想。库将携带默认设置是有道理的,而应用程序将能够覆盖它们。您是否会详细说明如何将设置从库的 app.config 传播到正在执行的程序集的 app.config,或者将我引导至相关资源? @user1531508 作为不得不接管不想遵循 Microsoft/.Net“首选用法”(又名最佳实践)的“特殊”代码的人,我会说不。与替代方案相比,遵循最佳实践是圣杯。不,托德的意见不如微软的重要。【参考方案3】:

乔恩,很多意见都没有正确回答你的问题。

我会给出我的意见,然后告诉你如何按照你的要求去做。

我看不出程序集没有自己的配置文件的原因。为什么第一级原子性(这是一个真实的词?)在应用程序级别?为什么不在解决方案级别?这是一个武断的、最佳猜测的决定,因此是一个意见。如果您要编写一个日志库并希望为其包含一个配置文件,该配置文件将在全局范围内使用,您为什么不能挂钩到内置的设置功能?我们都做到了……试图为其他开发人员提供“强大”的功能。如何?通过做出固有地转化为限制的假设。这正是 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 条目。

【讨论】:

-1:您的意见本身并不重要。事实很重要。 .NET 从第一天开始创建,以便库的调用者确定库中项目的配置。这是唯一对配置有意义的事情,因为库的不同调用者可能需要不同的配置。 @JohnSaunders “库的不同调用者可能需要不同的配置。”确切地说,它们“可能”需要不同的配置,并且您的逻辑在配置确实依赖于调用者的所有情况下都非常有意义。但是有几种情况,配置在类库内部使用,配置完全一样,不管调用者是什么。如果您有 10 个应用程序使用一个库,那么将完全相同的配置复制并粘贴到 10 个配置文件中会更糟。 @ToddBeaulieu:我认为你想要的词是“原子性”。 在插件架构中,如果所有插件都有自己的配置文件,这确实是有意义的。 @RMuesi Noone 说它永远不会改变,只是它不依赖于库的调用者。配置可能会根据您是在调试库还是在生产版本进行更改。它可以根据您正在构建的环境等而改变。【参考方案4】:

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

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

希望这些信息对您有用。

见,并发布有关您找到的解决方案的 cmets。

编辑:

在下一个链接中,您有一个 app.config,其中包含 log4net 部分:

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

【讨论】:

+1 完全正确; app.config 是从最终运行的实际程序加载的......而不是单个类库。坦率地说,有多少人不知道这个非常基本的事实,这有点令人困惑。 也许人们来自 Java 语言,你有一个 log4java.properties 和一个单独的应用程序属性文件。【参考方案5】:

如果您想使用 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;
      

现在您可以直接调用具有所需路径和模式的 SetLogger 来在 Global.asax 应用程序启动函数中设置记录器,而不是调用 XmlConfigurator.Configure(new FileInfo("app.config"))。

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

        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 中编写单行代码。

【讨论】:

我觉得这是最好的答案......而不是讨论是否应该允许库配置文件......这个答案回答了OP使用Log4net的问题 尽管问题以 log4net 为例,但实际问题通常是关于配置的。我想说关于 log4net 的答案实际上是无关紧要的。【参考方案6】:

实际上,在极少数情况下,您可以将 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 Container 和 Injection Factory 来解耦组织我们的 N 层 WCF 架构,没有任何元数据。我们添加了带有 [Service Contract] 接口和通用应用程序的 externall ClassLibrary dll。配置以便从客户端部分读取端点,并在一处轻松添加/更改它们。

【讨论】:

【参考方案7】:

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

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

否则,将 App.config 添加到类库不会做任何事情。

【讨论】:

【参考方案8】:

对于非手动创建 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. 稍作修改,我们将类库的配置文件粘贴到可执行配置中。 (有一种方法可以将类库配置文件保留在外部,然后从可执行文件的配置中引用它。

因此,您可以为类库创建一个 app.config,但如果您没有将它与父应用程序正确集成,它就毫无用处。 看看我之前写的:link

【讨论】:

【参考方案9】:

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

据我所知,没有关于手动执行此操作的反指示。我认为这是一种常见的用法。

关于log4Net的配置,你不必把配置放到app.config中,你可以在你的项目中有一个专用的conf文件,同时也可以有一个app.config文件。

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

【讨论】:

在库项目中添加app.config 并没有什么坏处,不。但两者都不会被使用。 @AndrewBarber 它将用于测试项目。见***.com/a/31389495【参考方案10】:

我建议使用 Properties.Settings 在类库中存储 ConnectionStrings 等值。例如,当您尝试添加表适配器时,所有连接字符串都会根据 Visual Studio 的建议存储在其中。 enter image description here

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

var cs=  Properties.Settings.Default.[<name of defined setting>];

【讨论】:

以上是关于类库的 app.config的主要内容,如果未能解决你的问题,请参考以下文章

类库和 ASP.NETvNext 类库的区别?

包括来自类库的服务引用

ArcObject类库的AO参考类库

在同一个项中引用同一类库的多个版本

类库的 app.config

Visual Studio 中类库的 Application Insights