My best:
I wrote a C# application that used plugins and (stupidly) in version 1.0, added strong names to the assemblies that all plugins had to consume. This became a serious problem a couple of versions later as I became unable to make meaningful changes to the API without breaking every single existing plugin (many of whose developers had disappeared, and, consequently, could not even be recompiled against new binaries). I wanted to keep backward compatibility, but polluting the app with two different sets of API binaries wasn't practical.
The solution? New assemblies in version 3.0 with the old API rearranged across DLLs and extended with the new functionality. When the app attempted to install an old plugin, it would disassemble the plugin's DLL (using the command-line tools; not even doing this properly), search through the resulting .il files for the references to the strongly-named assemblies, change those to the un-strongly-named assembly references, add the new assemblies, then recompile the il source back to a DLL (with ilasm).
As ridiculous as that sounds (and as potentially breaking), it actually worked very, very well. And nobody needed to rewrite any plugins.