Using ILMerge to hide Dependencies
A few days ago I needed to install a nuget package to get some work done. Unfortunately, it depends on a higher version of Newtonsoft.Json
than what we were currently using. I briefly looked into upgrading the version of Newtonsoft.Json
across the application, but that ended up looking like more work than the original task I was working on.
After thinking about it a little more, I was asking myself, why I should even have to care that a package I want to take a dependency on is relying on something else? Why should I need to setup assembly bindings to try to redirect dependent assemblies to higher or lower versions based on what the rest of my application is running?
Then the idea hit me to ditch the nuget package all together. I decided to grab the assembly I wanted to use, and the version of Newtonsoft.Json
that it depends on and merge them into one. This allows me to have a single assembly without having to worry about whether or not it's dependencies are going to play nice with the rest of the application.
To do this, I put the two assemblies I wanted to merge into a folder, renamed the original assembly to <assembly>.old.dll
and ran the following command.
ILMerge.exe /out:<assembly>.dll /internalize /target:library /targetplatform:v4,C:\Windows\Microsoft.net\Framework64\v4.0.30319 .\<assembly>.old.dll .\Newtonsoft.Json.dll
Here's a breakdown of what that command does:
/out:<assembly>.dll
outputs the result to<assembly>.dll
./internalize
marks all assemblies that are being merged into the first specified assembly as internal. This is important, as it makes sure we don't have duplicate namespaces with our other reference toNewtonsoft.Json
./target:library
tells ILMerge that we're merging assemblies, you can also use/target:exe
if you're merging into an executable./targetplatform:v4,C:\Windows\Microsoft.net\Framework64\v4.0.30319
lets ILMerge know that the new assembly should target .NET 4..\<assembly>.old.dll
this is the first assembly that we specify, so it's going to be the one that's not marked as internal. This should always be the main dependency that you want access to from your application..\Newtonsoft.Json.dll
this is the assembly you want to merge in..\<another_assembly>.dll
You can tack on as many assemblies at the end as you want. It will merge them all into a single dll.
After the merge was complete, I was able to add a reference to the produced dll. This worked just like the nuget package version, except I didn't have to worry about the Newtonsoft.Json
dependency, at all.
In the near future, I'm planning on submitting a pull request to the repository of the nuget package that I had issues with. Hopefully if it's accepted the nuget package will no longer have any dependencies and will be a little easier to work with.
On the surface, this seems like a great way to deal with dependencies of nuget packages. However, I feel like since it's not wide-spread and we're all still dealing with these upgrade issues that there's a catch I'm not seeing. Let me know on twitter or by email what I'm missing.