web-dev-qa-db-fra.com

Utilisation de plusieurs versions du même DLL

J'ai été chargé de créer un nouveau module pour une application et j'ajoute donc de nouvelles DLL au projet. Tout va bien.

Cependant, dans mes DLL, j'aimerais utiliser une nouvelle version d'un DLL externe (sur lequel je n'ai aucun contrôle). Si je ne fais que référencer le nouveau DLL et travailler avec celui-là uniquement, mon code fonctionnera, mais l'ancien code cessera de fonctionner.

Could not load file or Assembly 'itextsharp, Version=5.0.6.0, Culture=neutral,
PublicKeyToken=8354ae6d2174ddca' or one of its dependencies. The located Assembly's
manifest definition does not match the Assembly reference. (Exception from HRESULT:
0x80131040)

J'ai essayé une astuce simple pour changer le nom des DLL, mais c'était apparemment un peu trop naïf de ma part, pour penser que cela fonctionnerait. J'ai essayé d'utiliser les alias externes (en les définissant dans mes références), mais je ne sais toujours pas comment mettre deux fichiers du même nom dans un dossier BIN ...

Que devrais-je faire?

21
Shaamaan

Vous pouvez charger une autre version dans un AppDomain spécifique

Peut-être trop détaillé, mais voici un article qui montre comment utiliser AppDomains dans un contexte utile et comment ils fonctionnent:

http://msdn.Microsoft.com/en-us/magazine/cc164072.aspx

Dans un sens très basique, il s’agit de cet exemple de code:

    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    ...

    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (/*some condition*/)
            return Assembly.LoadFrom("DifferentDllFolder\\differentVersion.dll");
        else
            return Assembly.LoadFrom("");
    }
14
sehe

Une autre option viable consiste à utiliser extern, comme décrit ici: 

http://blogs.msdn.com/b/abhinaba/archive/2005/11/30/498278.aspx

5
fozylet

Supposons que vous avez une structure de projet comme suit:

Project Diagram

... où A et B sont des bibliothèques de classes et C est un projet de type exécutable (tel qu'un projet de test unitaire ou de console). 

Supposons que la structure du dossier ressemble à ceci:

ABC.sln
A/A.csproj
A/...
B/B.csproj
B/...
C/C.csproj
C/...
lib/thirdparty4/thirdparty.dll
lib/thirdparty5/thirdparty.dll

Si nous essayions de référencer naïvement nos projets ensemble, nous aurions un problème: deux versions de thirdparty.dll seront copiées dans le même dossier (le répertoire de sortie (c'est-à-dire, bin) de C). Nous avons besoin d’un moyen pour C de copier les deux dll dans son répertoire de sortie et de fournir un mécanisme pour référencer l’un ou l’autre.

Pour résoudre ce problème, j'ai modifié C.csproj afin qu'il contienne les éléments suivants:

<ItemGroup>
  <Content Include="..\lib\thirdparty4\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty4\thirdparty.dll</Link>
  </Content>
  <Content Include="..\lib\thirdparty5\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty5\thirdparty.dll</Link>
  </Content>
</ItemGroup>

Cela lui indiquera de créer à la fois thirdparty4\thirdparty.dll et thirdparty5\thirdparty.dll dans son répertoire de sortie. 

Maintenant, après avoir construit C, son répertoire de sortie ressemble à ceci:

C\bin\Debug\A.dll
C\bin\Debug\B.dll
C\bin\Debug\C.dll
C\bin\Debug\thirdparty4\thirdparty.dll
C\bin\Debug\thirdparty5\thirdparty.dll

Pour indiquer à C d'utiliser ces deux dll, j'ai ajouté un fichier App.config, avec les éléments suivants:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-Microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="4.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
        <codeBase version="4.0.0.0" href="thirdparty4\thirdparty.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="5.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
        <codeBase version="5.0.0.0" href="thirdparty5\thirdparty.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Cela indiquera à l’Assemblée, en fonction de la version requise, d’utiliser l’un ou l’autre DLL, ces deux éléments étant disponibles dans les sous-dossiers du répertoire de sortie. (Les éléments bindingRedirect sont facultatifs, mais vous pouvez les utiliser si vous avez besoin d'une gamme de révisions à laquelle appliquer ceci.)

4
Jay Sullivan

Si la solution AppDomains ne s'applique pas dans votre cas, vous êtes pressé par le temps, vous avez des exigences contradictoires (comme que se produit jamais) et vous ne craignez pas les piratages ridicules:

  • Décompiler la version plus récente de Assembly à l'aide de l'outil ildasm (élément de l'invite de commande du développeur fourni avec Visual Studio)
  • Editez le fichier .il généré pour rechercher/remplacer les références d’espace de noms Assembly. En utilisant l'exemple cité, cela changerait de itextsharp.X à itextsharp.new.X
  • De même, modifiez la valeur de AssemblyTitleAttribute. Cela nécessite de traduire les caractères ASCII en hexadécimal.
  • Recompiler le fichier .il en utilisant ilasm
  • Notez qu'il peut être nécessaire de répéter cette opération pour tous les assemblys dépendants (par exemple - Someassembly.core.w importe).
  • Ajouter les nouveaux fichiers .dll à votre projet avec un nom différent et les référencer explicitement (plutôt que via nuget ou autre)

Hey, ne me regarde pas comme ça. J'ai dit bidouille ridiculement artificielle ...

1
Vecht

Vous pouvez également compter sur la redirection des liaisons d'assembly pour votre assembly nommé fort, comme décrit dans http://msdn.Microsoft.com/en-us/library/2fc472t2.aspx .

Vous n'auriez qu'une seule version du fichier (la plus récente) et les deux références y remédieraient.

1
fsimonazzi