Ссылка на две равные сборки, отличаются только открытые ключи

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

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

  

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

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

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

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

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

UPDATE

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

7 голосов | спросил Sandor Drieënhuizen 16 12009vEurope/Moscow11bEurope/MoscowMon, 16 Nov 2009 23:07:00 +0300 2009, 23:07:00

2 ответа


0

Интересно, сработает ли 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;
}

Я предполагаю, что вы ссылались на предпочитаемую версию и можете использовать тип SomeTypeInReferencedAssembly, чтобы получить Assembly; Вы также можете использовать:

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

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

ответил Marc Gravell 16 12009vEurope/Moscow11bEurope/MoscowMon, 16 Nov 2009 23:13:28 +0300 2009, 23:13:28
0

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

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

ответил Adam Robinson 16 12009vEurope/Moscow11bEurope/MoscowMon, 16 Nov 2009 23:27:40 +0300 2009, 23:27:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132