Click here to Skip to main content
15,887,336 members
Articles / Programming Languages / C#
Tip/Trick

Combining Multiple .NET Assemblies

Rate me:
Please Sign up or sign in to vote.
4.95/5 (125 votes)
20 Mar 2015CPOL2 min read 55.6K   520   145   25
Combining multiple .NET assemblies by customizing MSBuild's project file.

Introduction

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, then 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:

Note that MyExecutable's project file (MyExecutable.csproj) is an XML based file and if we inspect its contents, 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 resource files that need 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:

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

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

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:

XML
<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 these changes in MyExecutable.csproj file and rebuild the solution in Release mode:

Last thing I would like to emphasize 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 the same .NET language.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer GemBox Ltd.
Croatia Croatia
I'm a developer at GemBox Software, working on:

  • GemBox.Spreadsheet - Read, write, convert, and print XLSX, XLS, XLSB, CSV, HTML, and ODS spreadsheets from .NET applications.
  • GemBox.Document - Read, write, convert, and print DOCX, DOC, PDF, RTF, HTML, and ODT documents from .NET applications.
  • GemBox.Pdf - Read, write, edit, and print PDF files from .NET applications.
  • GemBox.Presentation - Read, write, convert, and print PPTX, PPT, and PPSX presentations from .NET applications.
  • GemBox.Email - Read, write, and convert MSG, EML, and MHTML email files, or send and receive email messages using POP, IMAP, SMTP, and EWS from .NET applications.
  • GemBox.Imaging - Read, convert, and transform PNG, JPEG, and GIF images from .NET applications.

Comments and Discussions

 
QuestionAbout file types in library Pin
leiyangge9-Dec-15 14:26
leiyangge9-Dec-15 14:26 
AnswerRe: About file types in library Pin
Mario Z9-Dec-15 21:14
professionalMario Z9-Dec-15 21:14 
GeneralRe: About file types in library Pin
leiyangge9-Dec-15 21:48
leiyangge9-Dec-15 21:48 
GeneralRe: About file types in library Pin
Mario Z9-Dec-15 22:03
professionalMario Z9-Dec-15 22:03 
QuestionWhat's the use? Pin
Sergey Alexandrovich Kryukov25-Mar-15 4:26
mvaSergey Alexandrovich Kryukov25-Mar-15 4:26 
AnswerRe: What's the use? Pin
Mario Z25-Mar-15 7:27
professionalMario Z25-Mar-15 7:27 
GeneralRe: What's the use? Pin
Sergey Alexandrovich Kryukov25-Mar-15 7:53
mvaSergey Alexandrovich Kryukov25-Mar-15 7:53 
GeneralRe: What's the use? Pin
Mario Z25-Mar-15 11:45
professionalMario Z25-Mar-15 11:45 
GeneralRe: What's the use? Pin
Sergey Alexandrovich Kryukov25-Mar-15 12:26
mvaSergey Alexandrovich Kryukov25-Mar-15 12:26 
GeneralRe: What's the use? Pin
Mario Z25-Mar-15 15:30
professionalMario Z25-Mar-15 15:30 
Yes I must admit I got a bit upset for bad vote, it's just you are my first downvoter (probably not the last Wink | ;) ). Also I apologize for calling you rude, I should not have done that and you are absolutely right, this is a free community and I shouldn't have imposed myself.

Now back to a discussion, first regarding the source code, I really thought there was no need for it here.
The image shows the resulting combined assembly and snippet codes provide all the necessary changes that need to be made to accomplish it.
What I was thinking is if this solution suites someone then he would try it out on his solution, it would literally take just few minutes, after all that is probably the reason why he was searching for this topic.
Nevertheless I will take your advice and provide a source code.

I must admit that it seems to me that you have the same criteria for an article and tip/trick posts. Note that CP Submission Guidelines states:
"Tips n tricks are meant to be very, very short tips, snippets or even just a one-liner you came across that saved your day. Articles are for presenting more detailed ideas."
Again please understand that this is tip/trick and I was trying to keep it simple as much as possible.

"Are you still able to add new projects to the solution, move parts of code from one project to another one?"
You can freely move parts of the project, but regarding the new projects you can add it but without adjusting the project's file with the above approach that newly added project will be built as a separate assembly.

"How, how can you know what "every developer" thinks about it?"
It may seem as an exaggeration, it probably is a bit, but I'm pretty sure about component developers because I work at a component vendor company and I'm familiar with work of few others.
But in short you can just take a look at couple of components and see that the opinion is mutual on this matter.

"Your arguments based solely on the assumption that the merge is useful itself, the value is having one file instead of few, and your only argument is "...
I'm not sure why you are ignoring the few use cases that I already mentioned (portable applications, pluggable applications, CI simplification), these where not my use cases but I do remember them.

Nevertheless one of my use cases, when you are providing a usable component you want to simplify a specific task to developers. So keeping in mind that your goal is to ease other developers task doesn't it feel only natural to make the component available to other developers in most simplest manner possible, I believe you will agree that there is no simpler way then adding a single file and its reference.
If some user has difficulties in adding your solution into a project he will just give up.
Also there are no benefit of having multiple files (your solution is still separated in the organized projects), you are just making other developers job harder.
Now yes this does not reflect on NuGet and setup distribution, but some developers prefer to consume the components as private assemblies.
Also the component's deployment is just simpler, it is easier to build documentation, obfuscate, create NuGet package, create setup, etc. by manipulating with one DLL rather than N DLLs.
There are probably other benefits as well, but I'm taking much for granted nowadays so unfortunately nothing else comes to my mind right now.

Again I need to point out that there are various use cases, that is why people are searching for the solutions to combine their assemblies, but this is not an article that talks about why you would want to combine your assemblies, this is a tip that demonstrates one simple way how this can be done.
GeneralRe: What's the use? Pin
Sergey Alexandrovich Kryukov25-Mar-15 16:40
mvaSergey Alexandrovich Kryukov25-Mar-15 16:40 
GeneralRe: What's the use? Pin
Mario Z26-Mar-15 7:24
professionalMario Z26-Mar-15 7:24 
GeneralRe: What's the use? Pin
Sergey Alexandrovich Kryukov26-Mar-15 9:05
mvaSergey Alexandrovich Kryukov26-Mar-15 9:05 
GeneralRe: What's the use? Pin
Mario Z27-Mar-15 5:05
professionalMario Z27-Mar-15 5:05 
GeneralNow it's clear, but... Pin
Sergey Alexandrovich Kryukov27-Mar-15 12:28
mvaSergey Alexandrovich Kryukov27-Mar-15 12:28 
GeneralRe: Now it's clear, but... Pin
Mario Z27-Mar-15 23:42
professionalMario Z27-Mar-15 23:42 
GeneralAgain: it won't build Pin
Sergey Alexandrovich Kryukov28-Mar-15 0:07
mvaSergey Alexandrovich Kryukov28-Mar-15 0:07 
GeneralRe: Again: it won't build Pin
Mario Z28-Mar-15 0:17
professionalMario Z28-Mar-15 0:17 
GeneralRe: Again: it won't build Pin
Mario Z31-Mar-15 3:08
professionalMario Z31-Mar-15 3:08 
GeneralRe: Again: it won't build Pin
Sergey Alexandrovich Kryukov31-Mar-15 3:44
mvaSergey Alexandrovich Kryukov31-Mar-15 3:44 
GeneralRe: Again: it won't build PinPopular
Mario Z31-Mar-15 3:55
professionalMario Z31-Mar-15 3:55 
GeneralRe: Again: it won't build Pin
Sergey Alexandrovich Kryukov31-Mar-15 3:59
mvaSergey Alexandrovich Kryukov31-Mar-15 3:59 
GeneralIt works, failed to reproduce the problem Pin
Sergey Alexandrovich Kryukov31-Mar-15 4:20
mvaSergey Alexandrovich Kryukov31-Mar-15 4:20 
GeneralRe: What's the use? Pin
stixoffire7-Jul-15 5:54
stixoffire7-Jul-15 5:54 
GeneralRe: What's the use? Pin
Mario Z7-Jul-15 21:54
professionalMario Z7-Jul-15 21:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.