web-dev-qa-db-fra.com

Utilisation de différentes versions du même assembly dans le même dossier

J'ai la situation suivante

Projet A

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

Projet B

 - Uses NHibernate
 - Uses Castle Windsor v2.1

Dans le dossier bin du projet A, j'ai les dll Castle.DynamicProxy2.dll v2.2 et NHibernate. Maintenant, le problème est que NHibernate dépend de Castle.DynamicProxy2.dll v2.1 qui n'est pas là. Comment puis-je résoudre cette situation.

61
Hemanshu Bhojak

J'ai utilisé la configuration suivante pour résoudre le problème.

<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>
90
Hemanshu Bhojak

Une chose très, très, très importante que l'on pourrait manquer s'il ne fait pas assez attention.

L'assembly que vous écrivez dans la balise de version codeBase, doit être avec un nom fort.

À partir du lien suivant: http://msdn.Microsoft.com/en-us/library/efs781xb.aspx

Pour les assemblys sans nom fort, la version est ignorée et le chargeur utilise la première apparence de <codebase> dans <dependentAssembly>. S'il existe une entrée dans le fichier de configuration d'application qui redirige la liaison vers un autre assembly, la redirection sera prioritaire même si la version de l'assembly ne correspond pas à la demande de liaison.

Une solution (ou solution de contournement) consisterait à installer les deux versions dans le Global Assembly Cache (GAC) sur la ou les machines sur lesquelles votre logiciel doit exécuter et référencer les assemblys en utilisant leurs noms forts. Cela suppose que les assemblys ont effectivement des noms forts.

L'installation dans GAC sera pénible si vous avez plusieurs développeurs ou si vous prévoyez de déployer votre solution sur plusieurs ordinateurs (par exemple en tant qu'application utilisateur final). Dans ce cas, je crois (mais je me trompe peut-être) que votre seule option est de fusionner l'une des deux versions dans l'assemblage nécessitant cette version. Dans votre cas spécifique, vous avez besoin de Castle.DynamicProxy2.dll v2.1 à fusionner dans NHibernate.dll.

Vous pouvez utiliser un outil appelé ILMerge pour fusionner les assemblys. La commande que vous devrez exécuter ressemble à ceci (non testé):

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

Le /internalize switch indique à ILMerge de marquer tous les types du deuxième assembly (Castle dans ce cas) internal dans l'assembly de sortie. Sans cela, vous pourriez obtenir des erreurs de compilation lorsque vous essayez de compiler un projet référençant à la fois votre nouveau NHibernate.dll et la version étagère de Castle.DynamicProxy2.dll v2.2, car ils contiendront des classes portant exactement les mêmes noms.

9
Jørn Schou-Rode

Je ne pense pas que la solution d'Hemanshu Bhojak soit une bonne solution car vous ne voulez pas charger deux versions du même Assembly dans le même contexte. Cet article explique pourquoi:

http://msdn.Microsoft.com/en-us/library/dd153782.aspx#avoid_loading_multiple_versions

2
Jonathan Parker