65.9K
CodeProject 正在变化。 阅读更多。
Home

合并多个 .NET 程序集

2015年3月20日

CPOL

2分钟阅读

viewsIcon

59943

downloadIcon

558

通过自定义 MSBuild 的项目文件来合并多个 .NET 程序集。

引言

任何寻找将多个程序集合并成单个文件解决方案的人可能听说过 ILMerge、SmartAssembly 等工具。
另一种已知解决方案是将 DLL 嵌入为资源(如果有人感兴趣,这里有一篇不错的文章解释了这种方法:从嵌入式资源加载 DLL[^])。

然而,在某些情况下,我注意到这些方法的使用是不必要的。
如果我们拥有这些程序集的源代码,那么我们可以在编译时将所有源代码文件导入到单个项目中,从而实现合并。

在本技巧中,我将尝试简要解释如何实现这一点。

为了演示目的,假设我们有一个控制台应用程序(我们的主程序集),它引用并使用了两个类库(我们的辅助程序集),并且我们希望将它们全部合并到一个文件中

构建此解决方案时,我们如预期的那样得到三个程序集

请注意,MyExecutable 的项目文件 (MyExecutable.csproj) 是一个基于 XML 的文件,如果我们检查其内容,我们可以找到几个 ItemGroup 节点。这些节点包含子元素,这些子元素定义了构建过程的输入。这些子元素可以引用应用程序的需要编译的源文件,或需要复制的资源文件,或需要在构建过程中包含的程序集(如果有人感兴趣,您可以阅读有关 Visual Studio 项目文件的更多信息,请访问 MSDN MSBuild)。

现在让我们找到引用我们包含的程序集的 ItemGroup 节点

<ItemGroup>
  <ProjectReference Include="..\MyLibrary1\MyLibrary1.csproj">
    <Project>{ea53ca82-13d7-4be1-b95a-4d9d7853d46e}</Project>
    <Name>MyLibrary1</Name>
  </ProjectReference>
  <ProjectReference Include="..\MyLibrary2\MyLibrary2.csproj">
    <Project>{c31d21f3-e86a-4581-b4e8-acae6644d19e}</Project>
    <Name>MyLibrary2</Name>
  </ProjectReference>
</ItemGroup>

在这里,我们将添加一个条件,该条件将指示 MSBuild 在构建 MyExecutableDebug 模式下使用这些项目引用

<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">

但是对于 Release 模式,我们将包含 MyLibrary1MyLibrary2 的所有源代码文件以供编译。我们将通过使用通配符 ("\**\*.cs") 来实现这一点,该通配符将包含目录及其子目录中的所有 CS 文件。通配符还会包含一些不需要的源代码文件(在本例中,这些是 obj 文件夹中的 TemporaryGeneratedFile_[guid].cs 文件和 Property 文件夹中的 AssemblyInfo.cs 文件),因此我们需要排除它们

<ItemGroup Condition=" '$(Configuration)' == 'Release' ">
  <Compile Include="..\MyLibrary1\**\*.cs"
           Exclude="..\MyLibrary1\Properties\AssemblyInfo.cs;
                    ..\MyLibrary1\obj\**;
                    ..\MyLibrary1\bin\**">
    <Link>MyLibrary1\%(RecursiveDir)%(Filename)%(Extension)</Link>
    <Visible>false</Visible>
  </Compile>
  <Compile Include="..\MyLibrary2\**\*.cs"
           Exclude="..\MyLibrary2\Properties\AssemblyInfo.cs;
                    ..\MyLibrary2\obj\**;
                    ..\MyLibrary2\bin\**">
    <Link>MyLibrary2\%(RecursiveDir)%(Filename)%(Extension)</Link>
    <Visible>false</Visible>
  </Compile>
</ItemGroup>

就这样了,让我们将这些更改保存到 MyExecutable.csproj 文件中,并在 Release 模式下重新构建解决方案

最后,我想强调一点作为一种故障排除建议,因为我们实际上是将所有程序集源代码文件的编译移动到一个项目中,该项目需要能够编译这些文件。因此,您需要考虑以下几点

  • 主程序集需要拥有辅助程序集的所有引用、资源、设置等,才能成功构建。
  • 所有程序集都需要用相同的 .NET 语言编写。
© . All rights reserved.