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?
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("");
}
Une autre option viable consiste à utiliser extern
, comme décrit ici:
http://blogs.msdn.com/b/abhinaba/archive/2005/11/30/498278.aspx
Supposons que vous avez une structure de projet comme suit:
... 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.)
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:
Hey, ne me regarde pas comme ça. J'ai dit bidouille ridiculement artificielle ...
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.