Including indirect, optional dependencies in builds
So I’m writing an application that uses NHibernate as its data access layer. I’m also writing a bunch of integration tasks, and a console driver for them. I’ve written the tests, and I’m ready to fire up the real thing from the console.
The first thing that happens is that my application dies. “Could not load file or assembly NHibernate.ByteCode.Castle”.
The weirdness starts when I look at my project’s dependencies. It doesn’t depend directly on NHibernate either, but the assembly gets copied to the output folder. So do most of NHibernate’s dependencies. But not this one. Why is that?
NHibernate comes with a set of byte code providers. While this may seem overkill, I get that people may already be using such a library, and forcing consumers to include yet another one is a no-no. So the dependency to a byte code provider is not a hard dependency. This means that in order to include it in our Visual Studio builds, we need to perform some trickery.
Fortunately, the trickery is rather simple. First, reference the chosen byte code provider in the project that has the NHibernate reference. At this point you may feel compelled to already test the results – don’t bother, they’ll be equally disappointing. Since the reference isn’t actually used anywhere, the build process will skip it.
Instead, what you need to do is add a compile-time reference – that is, directly use a class included in the assembly. Here’s what I did:
#pragma warning disable 169
// This reference ensures that we always get NHibernate.ByteCode.Castle.dll
// as an indirect reference in other projects.
private static readonly Type proxyFactory = typeof (NHibernate.ByteCode.Castle.ProxyFactory);
#pragma warning restore 169
(The pragma does away with the compiler warning about an unused field.)
Of course, you can always accomplish the same thing with build scripts, this felt like a workable compromise. As a bonus, I don’t have to worry about this every time I reference this project.