如何告诉应用程序从我的自定义app.config文件而不是默认文件中读取<runtime> 配置转换外部化配置节

让我们说我正在创建一个名为 ConsoleApp2 的应用。

由于我正在使用某些第三方库,因此我的默认app.config文件正在生成类似

的代码
<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
    </dependentAssembly>
  </assemblyBinding>
</runtime>

那是因为我的解决方案引用了一个库的不同版本,所以它需要告诉所有人:“ 嘿,如果您要查找该库的任何 oldVersion ,只需使用 newVersion ”。没关系。

问题是我想定义一个单独的配置文件“ test.exe.config”,在其中进行一些设置并摆脱自动生成的设置。

为了向我的应用程序介绍新的配置文件,我正在使用类似的代码

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE","test.exe.config");

而且(几乎)完美运行。我在此处写了“ 几乎”,因为尽管正确地阅读了<appSettings>部分,但在我的自定义配置文件中并未查看<runtime>部分,但是应用看上去而是在默认配置文件中显示该文件,这是一个问题,因为我希望以后可以删除该文件。

那么,如何告诉我的应用程序也从我的自定义配置文件中读取<runtime>信息?


如何重现问题

重现我的问题的简单示例如下:

使用单个类创建名为 Classlibrary2 .Net Framework v4.6 )的库,如下所示:

using Newtonsoft.Json.Linq;
using System;

namespace Classlibrary2
{
    public class Class1
    {
        public Class1()
        {
            var json = new JObject();
            json.Add("Succeed?",true);

            Reash = json.ToString();
        }

        public String Reash { get; set; }
    }
}

请注意对 Newtonsoft 软件包的引用。库中安装的是 v10.0.2

现在使用名为 Program 的类创建一个名为 ConsoleApp2 .Net Framework v4.6 )的控制台应用程序,其内容如下:

using System;
using System.Configuration;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {

            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE","test.exe.config");

            var AppSettings = Configurationmanager.AppSettings;

            Console.WriteLine($"{AppSettings.Count} settings found");
            Console.WriteLine($"Calling Classlibrary2: {Environment.NewLine}{new Classlibrary2.Class1().Reash}");
            Console.ReadLine();

        }
    }
}

此应用程序还应该安装了 Newtonsoft ,但安装的版本是 v12.0.3

以“调试”模式构建应用程序。然后,在文件夹 ConsoleApp2 / ConsoleApp2 / bin / Debug 中创建一个名为 test.exe.config 的文件,其中包含以下内容

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <appSettings>
    <add key="A" value="1"/>
    <add key="B" value="1"/>
    <add key="C" value="1"/>
  </appSettings>
</configuration>

,请注意,在同一 Debug 文件夹中,还存在默认配置文件 ConsoleApp2.exe.config ,其内容类似于

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

这时,如果您运行该应用程序,它将毫无问题地进行编译,您应该会看到一个类似

的控制台。

如何告诉应用程序从我的自定义app.config文件而不是默认文件中读取<runtime>
      
    配置转换外部化配置节

请注意,正确地从我的自定义配置文件中读取了(3)设置。到目前为止一切顺利...

现在将默认配置文件重命名为 _ConsoleApp2.exe.config ,然后再次运行该应用程序。您现在应该得到一个 FileLoadException

如何告诉应用程序从我的自定义app.config文件而不是默认文件中读取<runtime>
      
    配置转换外部化配置节

再次,我如何告诉我的应用程序从我的自定义配置文件中读取<runtime>信息?


理性

我正在寻找这个问题的答案的原因如下:

发布应用程序时,我们将所有.exe和.dll文件放在一个文件夹中,而将自定义配置文件(带有设置等)放在另一个文件夹中,客户端的文件与此类似。

在包含.exe和.dll文件的文件夹中,我们尝试尽可能地少保存文件,因此,我被要求找到一种摆脱该 ConsoleApp2.exe.config 的方法。现在,由于上述绑定是写在该配置文件中的,所以我只是尝试将这些信息移到我们的自定义配置文件中...但是到目前为止,我仍未能实现:总是尝试从该中读取绑定重定向ConsoleApp2.exe.config ,因此,一旦我将其删除,我就会获得例外...

yang01104891 回答:如何告诉应用程序从我的自定义app.config文件而不是默认文件中读取<runtime> 配置转换外部化配置节

您可能正在寻找配置转换

背后的想法是,您可以在Visual Studio中创建多个配置,例如配置管理器中的 Debug,Release,Production,Test ... ,并使用默认配置文件以及所谓的转换。

注意,您可以在配置管理器中创建任意数量的配置。要添加新的,请单击“解决方案配置”(下拉菜单显示“ Debug”或“ Release”),然后选择“ Configuration Manager ...”。打开它,您会看到所有当前现有配置的列表。下拉组合框“活动解决方案配置”,然后选择“ <New...>”以添加更多内容。

这些转换指定了使特定配置与默认配置不同的原因-因此,您无需重复在默认配置中已经指定的配置,而只需提及不同之处,例如:

<configuration>
    <appSettings>
        <add key="ClientSessionTimeout" value="100"
            xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
    </appSettings>
</configuration>

除了App.Config文件之外,每种配置还有一个,即App.Debug.ConfigApp.Release.Config等。VisualStudio可以帮助您创建它们。

我已经在StackOverflow herethere中创建了答案,对其进行了详细说明,请看一下。

如果在Visual Studio中显示它们时遇到问题,请查看here


关于您的理论

转换通过将转换文件应用于默认配置文件来创建完整的配置文件。将编译生成的文件,并将其与其他编译文件一起放入“ bin”文件夹中。因此,如果选择了配置“发布”,则所有文件(包括转换后的配置文件)都将编译为“ bin \ Release”。

该配置文件的名称与exe文件的名称相同,并在末尾附加“ .config”(换句话说,二进制文件夹中没有“ .Release.config”,但有一个“ MySuperCoolApp.exe.config” “创建-为应用程序“ MySuperCoolApp.exe”。)

同样,其他配置也是如此-每个配置都会在“ bin”内部创建一个子文件夹-如果您使用的是脚本,则该子文件夹在构建后事件中可以称为$(TargetDir)

,

配置转换

鉴于当您尝试使用另一个(非本机)配置文件时,您试图找到一种“适当”替代它的解决方案时,会发生此问题。在我的回答中,我想退后一步,重点介绍您为什么要替代它的原因。根据问题中的描述,您可以定义自定义应用程序设置。如果我理解正确,您计划将其链接到目标项目,将“复制到输出”属性设置为“始终”,然后将其放在应用程序附近。

您可以使用Xdt transformations来转换现有的(本机)文件,而不是复制新的配置文件。为此,您可以创建转换文件并仅在其中声明要转换的部分,例如:

ConsoleApp2.exe.config

这种方法的好处是:

  • 灵活性:转换非常 flexible,您可以替换节,合并它们,设置/删除属性等。您可以具有特定于环境的(DEV / UAT / PROD)或构建特定于(Debug / Release)的转换。
  • 可重用性:定义一次转换,然后在所需的所有项目中重复使用。
  • 粒度:您只声明需要的内容,而无需复制粘贴整个配置。
  • 安全性:您让nuget和msbuild管理“本地”配置文件(添加绑定重定向等)

这种方法的唯一缺点是学习曲线:您需要学习语法并知道如何将转换粘合到MSBuild中的配置。

.NET Core支持转换,here is an example如何为web.config创建转换,但是您可以将转换应用于任何配置。

如果您开发.NET应用程序(不是.NET Core),那么我建议看一下Slowcheetah

关于转换有很多资源和有用的博客,它被广泛使用。如果您遇到困难,请与我联系。

从我的角度来看,配置转换是实现您的目标的正确解决方案,因此我强烈建议您考虑使用它,而不是调整运行时。

外部化配置节

如果您仍然希望将appSettings保留在公共位置,则可以使用ConfigSource属性来外部化配置节。检查thisthis线程以了解详细信息:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings xdt:Transform="Replace">
    <add key="A" value="1"/>
    <add key="B" value="1"/>
    <add key="C" value="1"/>
  </appSettings>
</configuration>

AppSettings部分包含File属性,该属性使您可以合并另一个文件中的参数。

此选项允许您替换配置的某些部分,但不能替换整个内容本身。因此,如果您仅需要appSettings,则完全适用-您只需将带有appSettings的配置文件放到与用户和补丁程序配置文件共享的公共位置(添加// ConsoleApp2.exe.config: <?xml version="1.0" encoding="utf-8"?> <configuration> <connectionStrings configSource="../commonConfig/connections.config"/> </configuration> // connections.config: <?xml version="1.0" encoding="utf-8"?> <connectionStrings> <add name="MovieDBContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=aspnet-MvcMovie;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\Movies.mdf" providerName="System.Data.SqlClient" /> </connectionStrings> file属性即可)位置。如果需要更多部分,则需要将它们提取为单独的文件。

,

要正确使用其他.config文件,您可以保留默认的一个来管理出价重定向,而另一个保留用于您的应用程序参数的文件。为此,Change default app.config at runtime看起来很棒。

您还可以关闭自动绑定重定向生成,仅使用手工制作的app.config文件。这里有一个示例:Need a way to reference 2 different versions of the same 3rd party DLL

修改 考虑到基本原理: 据我了解,您根本不需要app.exe.config文件。 您已经设法在其他地方放置和读取自定义内容。

仅保留绑定重定向。

您可以通过在运行时管理绑定重定向来摆脱它,就像在这里完成的那样:https://stackoverflow.com/a/32698357/361177 您还可以通过使代码查看配置文件来重新创建可配置的绑定解析器。

我的两分钱在这里:可行,但我认为不值得。

编辑2 该解决方案看起来很有前途https://stackoverflow.com/a/28500477/361177

本文链接:https://www.f2er.com/2931208.html

大家都在问