Ссылка на две равные сборки, отличаются только открытые ключи - PullRequest
7 голосов
/ 16 ноября 2009

Мой проект 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. Я еще не проверил это, но это может быть полезно всем, кто борется с этой проблемой.

Ответы [ 2 ]

4 голосов
/ 16 ноября 2009

Интересно, сработает ли 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, а когда система запрашивает старую - ложь".

3 голосов
/ 16 ноября 2009

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

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

...