2009-11-16 6 views
7

Mon projet Visual Studio 2008 fait référence à deux assemblages (externes) (A + B) référençant tous les deux le même troisième assemblage (C). Cependant, l'assembly A s'attend à ce que l'assembly C ait une clé publique différente de ce que l'assembly B s'attend à avoir.Référence deux assemblages égaux, seules les clés publiques diffèrent

Voici un exemple de l'exception évidente:

Impossible de charger le fichier ou l'assembly 'Newtonsoft.Json, Version = 3.5.0.0, Culture = neutral, PublicKeyToken = 9ad232b50c3e6444' ou une de ses dépendances. La définition de manifeste de l'assembly localisé ne correspond pas à la référence d'assembly. (Exception de HRESULT: 0x80131040)

Ofcourse, je ne serais pas en mesure de mettre les deux versions de C (uniquement différents par clé publique) dans le même répertoire, que leurs noms sont égaux. Deuxièmement, j'ai découvert que l'utilisation de la liaison d'assemblage à partir du fichier de configuration permet uniquement le mappage de version, et non le mappage de clé publique.

J'ai également essayé de placer l'un des assemblages C dans un répertoire séparé et de configurer le CLR pour qu'il recherche dans ce répertoire lors du chargement des assemblages. Je ne pouvais pas le faire fonctionner malheureusement. Je suis conscient que la recompilation d'une des bibliothèques externes (l'une d'entre elles est en open source) résoudrait ce problème mais je ne veux pas ajouter ce fardeau à mon plan de maintenance si ce n'est pas absolument nécessaire. Donc, ma question est: comment puis-je faire référence aux deux 'versions' de l'ensemble C, qui ne diffèrent que par la clé publique?

MISE À JOUR

je suis tombé sur this answer à une question connexe, en fournissant une solution intéressante en utilisant ILMerge. Je ne l'ai pas encore vérifié mais il peut être utile à tous ceux qui luttent avec ce problème.

+1

J'ai eu le même problème et [ceci] (http://stackoverflow.com/questions/2460542/using-different-versions-of-the-same-assembly-in-the-same-folder/2461746#2461746) est comment je l'ai résolu. –

Répondre

3

Je me demande si AssemblyResolve fonctionnerait:

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

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
{ 
    if (args.Name == "full name with old key") 
    { 
     return typeof(SomeTypeInReferencedAssembly).Assembly; 
    } 
    return null; 
} 

He're Je suppose que vous avez parlé de votre version préférée et peut utiliser le type SomeTypeInReferencedAssembly pour obtenir le Assembly; vous pouvez également utiliser:

return Assembly.Load("full name with new key"); 

Je ne l'ai pas essayé, mais ici, je suis essentiellement dire « déployer une version de la dll, et quand le système demande l'ancien - mensonge ».

+0

Merci, c'est une excellente solution. Espérons qu'un jour, l'un des assemblages de référence changera sa référence à C. –

+0

En fait, cela ne marche pas pour moi: il est maintenant dit que le manifeste d'assemblage du type que je retourne ne correspond pas au manifeste de la référence. Il a un point là ... –

+0

Pourriez-vous afficher le code incriminé dans votre question, Sandor? –

3

Vous ne devriez jamais avoir deux ensembles avec la même version mais différentes clés publiques, qui est une recette pour un désastre. Si les versions d'assemblage réelles sont différentes, la solution la plus simple est de les placer dans le global assembly cache (GAC). Cependant, cela ne fonctionnera pas bien si vous avez affaire à des instances de types définis en C et utilisés dans A et B (par exemple, C déclare MyType, et vous obtenez une instance de MyType de B et la transmettez à A. En ce qui concerne l'exécution, ces deux types n'ont absolument rien à voir l'un avec l'autre en dehors du partage d'un nom).

Si vous cherchez une solution temporaire, alors j'irais avec Marc; il semble que cela devrait fonctionner parfaitement.Cela étant dit, cependant, le fait que vous allez dans cette voie devrait être un drapeau rouge géant.

+0

Vous avez absolument raison. Heureusement, dans ce cas, je n'aurai jamais à passer des types autour de A et B parce qu'ils n'ont rien à faire les uns avec les autres. J'utilise la solution de Marc comme solution temporaire jusqu'à ce que A ou B change sa référence à C. Je sais que c'est un peu mauvais mais je suppose qu'il n'y a pas d'autre moyen que de lancer A ou B. –

Questions connexes