For a while now I've been researching a safe and local way of allowing two different versions of the same assembly to be used by an application. There are several SO and online articles dealing with the issue, however there is a "gotcha" with every solution I read.
Let's imagine we have two 3rd party libraries (we have no control over) that use different versions of Newtonsoft
(using Newtonsoft
as an example, it can be any other dependency). We want each of the 3rd party libraries to use the Newtonsoft
version they were built against. Following are some of the solutions I came across (from here and here):
Using a single version
Not ideal and sometimes not possible if each 3rd party library can work only against a specific version of a dependency.
Use GAC
Don't really want to.
Use AssemblyResolve
Will solve the main issue, however is considered unsafe to manually load two versions of the same assembly ourselves (rather than letting the runtime handle such task).
Use <codebase>
This is the most promising solution. The way I understand it is that I'm letting the runtime handle loading different versions of the same assembly, and my assumption is that it will do so in a safer way than me manually using AssemblyResolve
. I just think of this as a LAC (Local Assembly Cache)™
. However, to my understanding putting this in the App.config
of a class library (rather than executable) will be completely ignored. Here is my situation:
My app is developed in C++
and consumes .NET
assemblies through C++/CLI
. The .NET
assemblies consumed are the ones that depend on 3rd party libraries, which themselves depend on different versions of the same assembly (i.e Newtonsoft
). So really my question is there a way to use <codebase>
when the main app/executable is developed with C++
? Is there a way to get <codebase>
to be used with a .NET
class library?
If <codebase>
cannot work when the main app is a C++
one, is my only option to install the latest version of the dependency (i.e Newtonsoft
), and pray that it is backward compatible, so that 3rd party libraries that depend on older versions can still consume the latest version at runtime?
EDIT
I have followed Hans's suggestion by placing the <codeBase>
in a config file that has the same name as the executable, which works fine. For example the config structure can be as follows:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="DependencyName" culture="neutral" publicKeyToken="DependencyPublishToken" />
<codeBase version="1.0.0.0" href="DependencyName1.0.0.0/DependencyName.dll"/>
<codeBase version="2.0.0.0" href="DependencyName2.0.0.0/DependencyName.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
The only think I'd like to confirm (cannot find an answer anywhere) is this as safe as putting the assemblies in GAC? For example, would doing it this way still lead to issues mentioned here, or would it be safe because we're letting the runtime handle everything, and ensuring we only do the above for strong named assemblies?