Changing the version of an assembly reference on the fly
Today I wrote a small wrapper for the Quartz.NET scheduler library to integrate it into a project I’m working on. The project has been using MySQL Connector/.NET version 5.1 for its database needs for a while now, and I was intent on storing the Quartz scheduler jobs in the same database, using the same library.
Quartz comes with a pre-configured set of ADO.NET providers. It allows you to set the connection string, user name and whatnot, but what it doesn’t allow you to do is override the class names it uses to instantiate the ADO.NET provider classes. That’s a bit strange, since near as I can tell, it contains a mechanism that could allow that.
That, in itself, wouldn’t be a problem. But we were using MySql.Data.dll version 22.214.171.124 and the embedded property file in Quartz.dll specified version 126.96.36.199.
API-wise I suspected that nothing remarkable had changed, and that we’d be able to use 188.8.131.52 – in fact, my colleague had successfully recompiled Quartz from source to use that version, and everything had worked. But I really didn’t want to include the Quartz sources in our build, we have more than enough projects already.
I had a recollection that there is a mechanism that allows to change the assembly on the fly, but I couldn’t recall what it is. So I began to type my question at StackOverflow, and lo and behold, one of the suggested already-asked questions had a comment that mentioned Assembly Binding Redirection. That rang a bell, I followed the link, and no more than two minutes later I had managed to force Quartz to use the version of MySql.Data I wanted it to use. It’s this simple:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="myAssembly" publicKeyToken="32ab4ba45e0a69a1" culture="neutral" /> <bindingRedirect oldVersion="184.108.40.206" newVersion="220.127.116.11"/> <codeBase version="18.104.22.168" href="http://www.litwareinc.com/myAssembly.dll"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
I suppose I should qualify this post with a “be sure you know what you’re doing if you use this.” You need to be sure that the substituted assembly obeys the contract of the original, otherwise you will likely break things.
This is a powerful mechanism to have, and since I had forgotten it once already, I thought I’d document it here to make sure it doesn’t happen again. .-)