Reputation: 2030
I'm hoping that there is just something simple that I am missing here. I am trying to maintain two separate projects
ProjectName.Core &
ProjectName.Infrastructure
This is made in a typical Onion architecture so I can loosely couple my services and gain a greater flexibility. The Infrastructure project references the Core project. Once compiled they generate these DLLs
ProjectName.Core.dll &
ProjectName.Infrastructure.dll
But I would like to have it generate just 1 dll.
ProjectName.Infrastructure.dll (or even ProjectName.dll)
I have tried to use ILMerge to perform this operation but since Infrastructure references Core it throws an exception because it can't find the Core dll. It's obviously not looking within itself.
Now I need to maintain the separate projects because I have some other combinations that reference Core and another project that will be joined together such as
ProjectName.Core &
ProjectName.DataAccess &
ProjectName.Web
EDIT: My current solution calls out to ILMerge using an Nant build script. It merged together successfully. But when I try to use the merged DLL it throws an exception because it can't find the Core library.
<target name="merge.core">
<property name="temp.dir" value="${build.dir}\Temp\"/>
<mkdir dir="${temp.dir}" if="${not directory::exists(temp.dir)}"/>
<property name="tools.dir" value=""${directory::get-current-directory()}\Tools\""/>
<exec program="Tools\ILMerge\ILMerge.exe" workingdir=".">
<arg value="/t:Library"/>
<arg value="/ndebug"/>
<arg value="/out:"${build.dir}\Temp\ProjectName.Infrastructure.dll""/>
<arg value=""${build.dir}ProjectName.Core.dll""/>
<arg value=""${build.dir}Xceed.Compression.dll""/>
<arg value=""${build.dir}ProjectName.Infrastructure.dll""/>
<arg value=""${build.dir}ProjectName.Infrastructure.XmlSerializers.dll""/>
</exec>
<delete file="${build.dir}ProjectName.Core.dll"/>
<delete file="${build.dir}Xceed.Compression.dll"/>
<delete file="${build.dir}ProjectName.Infrastructure.dll"/>
<delete file="${build.dir}ProjectName.Infrastructure.XmlSerializers.dll"/>
<move file="${build.dir}\Temp\ProjectName.Infrastructure.dll" tofile="${build.dir}ProjectName.Infrastructure.dll"/>
<delete dir="${temp.dir}" if="${directory::exists(temp.dir)}"/>
</target>
To be a little more clear. I can use objects out of the Core library but not the Infrastructure library. Because once it tries to instantiate one of those objects it seems .NET attempts to load the dependency but cannot find it.
Upvotes: 6
Views: 919
Reputation: 457472
The most recent version of ILMerge has a /closed
option which works on the transitive closure of the merged assemblies. It solves this exact problem (see sections 2.6 Closed
and 4.1 Input assembly not merged in correctly
in the ILMerge.doc user manual).
Note that if your library attempts to dynamically load objects from a named assembly, then it would not work because the merged assembly name is different than the original assembly name. There isn't anything ILMerge can do in this case; you'll have to modify your dependency injection to account for this.
Upvotes: 0
Reputation: 50752
As I know that is not possible in Visual Studio, but you can compile every project as a netmodule and then join them together as a DLL. Compile like this:
csc misource1.cs misource2.cs misource3.cs /target:module
and then link together with the al.exe tool, see .netmodule Files as Linker Input and C# Assemblies.
Upvotes: 1
Reputation:
ILMerge! Almost as good as sliced bread.
http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx
Upvotes: 2