Using different versions of the same assembly in the same folder

46,240

Solution 1

I used the following configuration to resolve the issue.

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Castle.DynamicProxy2" publicKeyToken="407dd0808d44fbdc" />
                <codeBase version="2.1.0.0" href="v2.1\Castle.DynamicProxy2.dll" />
                <codeBase version="2.2.0.0" href="v2.2\Castle.DynamicProxy2.dll" />
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" />
                <codeBase version="1.1.0.0" href="v2.1\Castle.Core.dll" />
                <codeBase version="1.2.0.0" href="v2.2\Castle.Core.dll" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

Solution 2

One thing very, very, very important that one might miss if he is not paying enough attention.

The assembly you write in the codeBase version tag, must be strong named.

From the following link: http://msdn.microsoft.com/en-us/library/efs781xb.aspx

For assemblies without a strong name, version is ignored and the loader uses the first appearance of <codebase> inside <dependentAssembly>. If there is an entry in the application configuration file that redirects binding to another assembly, the redirection will take precedence even if the assembly version doesnt match the binding request.

Solution 3

One solution (or workaround) would be to install both versions in the Global Assembly Cache (GAC) on the machine(s) on which your software needs to run, and reference the assemblies using their strong names. This assumes that the assemblies do indeed have strong names.

Installing into the GAC will be a pain if you have more than a few developers or if you plan to deploy your solution to many computers (eg as an end-user application). In this case, I believe (but I might be wrong) that your only option is to merge one of the two versions into the assembly requiring that version. In your specific case, you need Castle.DynamicProxy2.dll v2.1 to be merged into NHibernate.dll.

You can use a tool called ILMerge to merge the assemblies. The command you will need to run looks something like this (untested):

ILMerge /t:library /internalize /out:Deploy/NHibernate.dll
    NHibernate.dll Castle.DynamicProxy2.dll

The /internalize switch tells ILMerge to mark all types from the second assembly (Castle in this case) internal in the output assembly. Without this, you might get compile errors when you try to compile a project referencing both your new NHibernate.dll and the shelf version of Castle.DynamicProxy2.dll v2.2, as they will contain classes with the exact same names.

Share:
46,240
Hemanshu Bhojak
Author by

Hemanshu Bhojak

Know more at http://hemanshubhojak.com

Updated on July 05, 2022

Comments

  • Hemanshu Bhojak
    Hemanshu Bhojak almost 2 years

    I have the following situation

    Project A

     - Uses Castle Windsor v2.2
     - Uses Project B via WindsorContainer
    

    Project B

     - Uses NHibernate
     - Uses Castle Windsor v2.1
    

    In the bin folder of Project A I have the dll Castle.DynamicProxy2.dll v2.2 and NHibernate dlls. Now the problem is that NHibernate is dependent on Castle.DynamicProxy2.dll v2.1 which is not there. How do I resolve this situation.

  • Sandor Drieënhuizen
    Sandor Drieënhuizen almost 14 years
    You could answer stackoverflow.com/questions/1744543/… with exactly this answer as well.
  • Jan Aagaard
    Jan Aagaard over 12 years
    Where are the dlls placed? Is in folders named v2.1 and v2.2 in the root of the website? Can you put the dlls in subdirectories to the bin folder?
  • Sreerag G
    Sreerag G about 12 years
    +1 for the only resource that has a working <codeBase> solution. Jan, the files can be anywhere, just xcopy them and adjust the filenames.
  • Hadas
    Hadas over 10 years
    First time I see that the name is without the dll extension.
  • Serge Intern
    Serge Intern about 8 years
    In this example where are the dlls placed relatively to application root?
  • Moslem Ben Dhaou
    Moslem Ben Dhaou about 7 years
    bindingRedirect should also work - Just for reference : stackoverflow.com/a/4452193/837623
  • Cyclion
    Cyclion almost 7 years
    for website the href should begin with "bin\" for instance <codeBase version="1.0.0.0" href="bin\folder\namedll.dll" />
  • ToolmakerSteve
    ToolmakerSteve over 6 years
    To clarify @MoslemBenDhaou's suggestion, bindingRedirect is helpful if "Project B" functions correctly with v2.2; it just needs to be told to use v2.2 instead of the version (v2.1) it was built with. If for some reason "Project B" must use exactly v2.1, then use the dual codeBase approach shown in the answer here. NOTE this answer - for two codeBases to work, the assemblies must be strong named.
  • PersyJack
    PersyJack almost 5 years
    I was struggling with making this work. What I didn't pay attention to was web.config is in the root folder so relative link couldn't find the file. After reading @Cyclion's comment above, everything worked.
  • Tobias Knauss
    Tobias Knauss over 4 years
    you can sign the assembly subsequently, if needed: stackoverflow.com/a/1380011/2505186