如何确保 C# 项目中配置文件的更改导致 DLL 被重建?

Posted

技术标签:

【中文标题】如何确保 C# 项目中配置文件的更改导致 DLL 被重建?【英文标题】:How to ensure changes to config file in C# project cause DLL to be rebuilt? 【发布时间】:2016-02-25 12:02:35 【问题描述】:

我在 Visual Studio 2015 中有一个 C# DLL 项目 (A),其中包含一个我想复制到输出的自定义配置文件,因此“复制到输出目录”设置为“如果较新则复制”。此 DLL 被同一解决方案中的另一个项目 (B) 引用。每当我重建项目 B 时,项目 A 的配置文件都会根据需要复制到其输出目录。

问题是,如果我修改 only 配置文件,它不会被复制到输出中。我认为这是因为项目 A 的输出没有改变,所以 MSBuild 不会费心将其复制到项目 B 的输出目录。

我发现的一种解决方法是将配置文件的内容类型设置为“嵌入式资源”,这会导致项目 A 在配置文件更改时重新构建。这行得通,但它有点黑客。有没有更好的方法来获得相同的行为,而无需在 DLL 中实际包含配置文件?

【问题讨论】:

有一个选项“总是复制”,你能试试吗? 我不想使用“始终复制”,因为会导致项目 B 一直在重建。我只希望在实际发生变化的情况下重建它。 我不会使用嵌入式资源。您也可以包含一个包含 const 的静态类。您将如何重新定义目标部署中包含的资源中的内容? 【参考方案1】:

好的,我想我已经找到了办法。在Microsoft.CSharp.Core.targets 中定义了一个CustomAdditionalCompileInputs 项目组,CoreCompile 目标依赖于此。所以我简单地添加了以下目标,以使 CoreCompile 依赖于具有构建操作 NoneContent 的所有文件:

  <Target Name="EnsureRecompiledOnConfigFileChanges" BeforeTargets="BeforeBuild">
    <!-- Recompile the project if any items of type "None" or "Content" change in case some of them are config files for a DLL. -->
    <ItemGroup>
      <CustomAdditionalCompileInputs Include="@(None)" />
      <CustomAdditionalCompileInputs Include="@(Content)" />
    </ItemGroup>
  </Target>

【讨论】:

如果您使用的是新的项目系统(如果您使用的是 SDK 样式的项目,那么您使用的是新的项目系统)那么您应该将自定义输入添加到 UpToDateCheckInput组,而不是CustomAdditionalCompileInputs【参考方案2】:

如果您使用的是 VS 2015,您还可以使用所谓的共享项目,当您引用共享项目时,共享项目中包含的源代码文件将被复制并同步到引用项目。通过这种方式,您可以将配置文件同步到其他引用项目,甚至在构建之前就发生了。

【讨论】:

【参考方案3】:

通常在使用 DLL 时,您不会配置 DLL,而是在使用 DLL 的项目中配置。

为了解释,假设您有一个 DLL,您可以在两个可执行项目中重用它。项目 B 引用项目 A,项目 C 引用项目 A。在这种情况下,项目 A 是 DLL,项目 B 和项目 C 是可执行文件。让我们进一步假设项目 A 使用配置设置,但项目 B 和项目 C 的实际值需要不同。

你在这种情况下所做的就是在exe B和exe C的应用程序配置中指定dll需要的设置。还要注意,当应用程序部署时,配置可能再次不同。

为了展示如何在应用程序配置中包含 DLL 的配置,我创建了以下内容。最重要的是命名空间在最终 app.config 中的使用方式。

类库

namespace ClassLibrary1

    public class Class1
    
        public string Message()
        
            return Settings.Default.Message;
        
    

控制台应用

namespace ConsoleApplication3

    class Program
    
        static void Main(string[] args)
        

            Console.WriteLine(new Class1().Message());
            Console.WriteLine(Settings.Default.Message);

            Console.ReadKey();

        
    

控制台应用配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="ConsoleApplication3.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
            <section name="ClassLibrary1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <applicationSettings>
        <ConsoleApplication3.Properties.Settings>
            <setting name="Message" serializeAs="String">
                <value>Hello from application</value>
            </setting>
        </ConsoleApplication3.Properties.Settings>
      <ClassLibrary1.Properties.Settings>
          <setting name="Message" serializeAs="String">
            <value>Hello from DLL</value>
          </setting>
        </ClassLibrary1.Properties.Settings>
    </applicationSettings>
</configuration>

使用 dll 运行此应用程序将显示以下输出

Hello from DLL

Hello from application

我希望这会有所帮助。

【讨论】:

我明白这一点,但对我来说也有通用设置(在引用项目之间共享)对我很有用。 如果你真的想重用设置,我会创建一个后期构建步骤,使用 XSLT 更改项目文件的配置。 还可以查看here 并阅读 Chris 的答案。他还很好地解释了为什么您通常不重用配置。但他也解释了你怎么能:)【参考方案4】:

您可以通过在项目 B 的项目设置中使用构建后事件命令来完成此操作,而不是使用“如果较新则复制”。只需设置一个 xcopy 命令,将 web.config 从项目 A 目录复制到构建输出文件夹项目 B。有一些构建参数有助于设置正确的目录,而不是硬编码所有目录名称。

看看这个***帖子:

Copy file(s) from one project to another using post build event...VS2010

【讨论】:

这可能有效,但需要手动列出所有引用项目 A 的项目中的所有配置文件。我认为将配置文件作为嵌入式资源比这“更干净”。

以上是关于如何确保 C# 项目中配置文件的更改导致 DLL 被重建?的主要内容,如果未能解决你的问题,请参考以下文章

c++调用c#的dll

如何从 c++ 项目中调用用 c# 创建的 dll 文件? [复制]

从 C# 调用 C++ 代码而不创建 dll?

如何创建项目的dll

C#项目中如何调用C#写的dll中的资源文件,如 xml文件

c#如何将一个类库打包成两个dll