2009-11-16 1 views
7

Проект My Visual Studio 2008 ссылается на две (внешние) сборки (A + B), которые оба ссылаются на одну и ту же третью сборку (C). Однако сборка A ожидает, что сборка C будет иметь открытый ключ, который отличается от того, что ожидает сборка B.Ссылка на две равные сборки, только открытые ключи отличаются

Вот пример очевидного исключения:

Не удалось загрузить файл или сборку 'Newtonsoft.Json, Version = 3.5.0.0, культура = нейтральной, PublicKeyToken = 9ad232b50c3e6444' или один из его зависимостей. Определение манифеста размещенной сборки не соответствует ссылке на сборку. (Исключение из HRESULT: 0x80131040)

Ofcourse, я не был бы в состоянии поставить обе версии C (только различающиеся открытым ключом) в той же директории, так как их имена совпадают. Во-вторых, я обнаружил, что использование привязки сборки из файла конфигурации допускает только сопоставление версий, а не отображение открытого ключа.

Я также попытался поместить одну из сборок C в отдельный каталог и настроить CLR для поиска в этом каталоге при загрузке сборок. К сожалению, я не мог добиться этого.

Я знаю, что повторная компиляция одной из внешних библиотек (одна из которых, по-видимому, будет открыта) исправит эту проблему, но я не хочу добавлять это бремя к моему плану обслуживания, если это не является абсолютно необходимым.

Итак, мой вопрос: как бы я упоминал обе версии «сборки С», которые отличаются только открытым ключом?

UPDATE

я наткнулся на this answer на соответствующий вопрос, обеспечивая интересное решение с использованием ILMerge. Я еще не проверил это, но может быть полезно любому, кто борется с этой проблемой.

+1

У меня была аналогичная проблема и [это] (http://stackoverflow.com/questions/2460542/using-different-versions-of-the-same-assembly-in-the-same-folder/2461746#2461746) как я это разрешил. –

ответ

3

Интересно, если AssemblyResolve будет работать:

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 Я предполагаю, что вы ссылки предпочтительный вариант и может использовать тип SomeTypeInReferencedAssembly, чтобы получить Assembly; Вы также можете использовать:

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

Я не пробовал, но здесь я, по существу говоря, «развернуть одну версию DLL, и когда система запросит старый - ложь».

+0

Спасибо, это отличное решение. Теперь давайте надеяться, что когда-нибудь одна из реферирующих сборок изменит свою ссылку на C. –

+0

На самом деле, это не работает для меня: теперь она говорит, что манифест сборки возвращаемого типа не совпадает с манифестом ссылки. У меня там есть точка ... –

+0

Не могли бы вы опубликовать оскорбительный код в своем вопросе, Сандор? –

3

Вы никогда не должны иметь два узла с же версиями но различных открытых ключей, это рецепт катастрофы. Если фактические версии сборки различны, то самым простым решением является размещение их в global assembly cache (GAC). Однако это не будет хорошо играть, если вы будете иметь дело с экземплярами типов, которые определены в C и используются как в A, так и в B (например, C объявляет MyType, и вы получаете экземпляр из B и передаете его к A. Что касается времени выполнения, эти два типа не имеют абсолютно никакого отношения друг к другу, кроме совместного использования имени).

Если вы ищете временное решение, я бы пошел с Марком; похоже, что он должен работать отлично.Однако, однако, тот факт, что вы идете по этой дороге, должен быть гигантским красным флагом.

+0

Ты абсолютно прав. К счастью, в этом случае мне никогда не придется передавать типы вокруг A и B, потому что они не имеют ничего общего друг с другом. Я использую решение Marc как временное исправление, пока A или B не изменят его ссылку на C. Я знаю, что это нехорошо, но я думаю, что нет правильного способа, кроме как выбросить A или B. –

Смежные вопросы