如何确保 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 依赖于具有构建操作 None
或 Content
的所有文件:
<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 文件? [复制]