合并多个 .NET 程序集 已翻译 100%

oschina 投递于 2015/03/21 07:30 (共 3 段, 翻译完成于 03-22)
阅读 5335
收藏 73
2
加载中

Whoever searched for a solution to merge multiple assemblies into a single file probably heard of tools like ILMerge, SmartAssembly, etc.

Another known solution is embedding the DLLs as resources (if anyone's interested here is a nice article that explains this approach: Load DLL From Embedded Resource[^]).

However on few occasions I noticed an unnecessary use of these approaches.
If we have these assemblies source codes than we can achieve the combining by importing all the source code files into a single project at compile time.

In this tip I'll try to explain briefly how to accomplish that.

For demonstration purposes let's say we have a console application (our main assembly) that references and uses two class libraries (our secondary assemblies) and we want to combine them all into a single file:

When building this solution we get three assemblies as expected:

已有 2 人翻译此段
我来翻译

Note that MyExecutable's project file (MyExecutable.csproj) is an XML based file and if we inspect its content we can find few ItemGroup nodes. These nodes contain child elements that define the build processes inputs. These child elements can refer to application's source files that need to be compiled, or a resource files that needs to be copied or assemblies that need to be included in the build process (if anyone's interested you can read more about Visual Studio project files on MSDN MSBuild).

Now let's locate the ItemGroup node that refers to our included assemblies:

<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>

Here we will add a condition that will indicate to MSBuild to use these project references when building MyExecutable in Debug mode:

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

已有 3 人翻译此段
我来翻译

But for Release mode we will include all the source code files from both MyLibrary1 and MyLibrary2 to be compiled as well. We will do this by using a wild card ("\**\*.cs") that will include all the CS files in the directory and its subdirectories. The wild card will also include some unwanted source code files (for this case those are TemporaryGeneratedFile_[guid].cs files in obj folder and AssemblyInfo.cs file in Property folder) so we will have to exclude them:

<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>

And that is it, let's save this changes in MyExecutable.csproj file and rebuild the solution in Release mode:

Last thing I would like to emphasise as a sort of troubleshooting advice, because we are literally moving the compilation of all assemblies source files into a single project, that project needs to be able to compile those files. So you need to consider the following:

  • The main assembly needs to have all the references, resources, settings, etc. of the secondary assemblies in order to build successfully.

  • All assemblies need to be written in same .NET language.

已有 2 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(13)

BinSys
BinSys
其实微软有现成的工具ILMerge~我都用这个。
Knixly
Knixly
改天试一下
web天空
web天空
之前研究过,是将DLL嵌入程序里,使用的时调出来
KBlackcn
KBlackcn
这个方法不好,还会丢失其他程序集的元数据,影响程序集级别的反射,正确的姿势应该是Costura.Fody
blu10ph
blu10ph
这些节点博阿含定义了构建过程输入的子元素. 阿含应该是包含吧?~
JRoger_
JRoger_
亲自试了一下,这种方式就是将别的项目的 cs 文件以链接的方式添加到当前项目中。大点儿的项目这样搞一下,会多出好多文件链接啊
Tian_Ya
Tian_Ya
新方法,收下
t
tsdyy
这个前提是有其他dll的源文件
JRoger_
JRoger_
这个第一次见
看客-申君健
看客-申君健
微软有合并程序集的工具,但这个方法是第一次见
返回顶部
顶部