Don't build strongly named assemblies unless you have to.
I've thought for a long time now that strongly named assemblies cause more trouble than they're worth (in most scenarios). This was brought home to me late last night at work as I struggled to recover from an ill-planned upgrade of NAnt. Basically, I got screwed by the fact that the version of NDoc that ships with NAnt is identical to the one I could download, but because they were built on different days, they had different build numbers, and that lead to some assembly load failures. OK, so that's more an argument for “don't base your build number on the date”, but that's another post. The experience still served to reinforce my low opinion of strongly-named assemblies.
See, the problem is that the whole strong-naming thing is supposed to give us two features:
- Tamper detection: If someone mucks with your assembly, the runtime will detect it because it's “signed“.
- Version policy: A strong name means that only exactly the version you request will satisfy a load attempt.
But of course, to do the first one right, you really need to have a whole PKI infrastructure in place, not to mention keeping private keys under tight control. And what do you do if it's an open source project? Even if you solve that problem, I still look at it and say, “If someone has the ability to mess with the bits in some DLL on my hard drive, I probably have bigger problems.”
I think point number two suffers from a severe case of over-engineering. Or, if you like, the issue is that the problem is just inherently very, very hard. Because the system has no way of inferring anything about whether two different versions are compatible or not, it has to assume that they never are. Which leads to problems like the one I had where NDoc.Core 1.3.1856.0 and NDoc.Core 1.3.1811.0 don't talk to each other. Of course, there are hooks like the <assemblyBinding> element in the config file (which I wound up using), but the rules are complex, and the file is hard to get right. Oh, and it fails silently if you get it wrong. The mere fact that the assembly loading and versioning versioning talk I used to give was three hours long should tell you something.
Having spent more and more of my time over the last few years writing real systems, I'm convinced that the simple approach to assembly loading is usually best: don't use strong names. Just put all your DLLs and EXEs in one directory, and the right thing will happen. In the rare event that you do need to make a breaking change to an assembly and you aren't recompiling the whole application, just change the name, like foo2.dll. Some may object that it's less aesthetically pleasing, but I think developers do a lot of stupid stuff in the name of making things prettier.
Will this approach always work? Of course not. BizTalk is one place where you're pretty well constrained to deploy to the GAC, and that means using strong names. Fine - not your choice, and there may well be a good reason for them making you do it that way. But I'd be willing to bet that 99% of the code out there isn't being deployed somewhere where strong names are a requirement. So make your life simple(r) and ditch strong names.
There - I feel better now. :)