2014-02-19 3 views
9

У меня возникает следующая ошибка при попытке скомпилировать утилиту, которая использует файлы, которые были развернуты для нашего клиента.Перенаправление привязки .NET для компиляции

Ассамблея '* A * version 2.0.1.2' использует '* B * версию 1.1.39.0', которая имеет более высокую версию, чем ссылочная сборка '* B * версия 1.1.32.0'.

Наш клиент не может использовать эти библиотеки DLL не проблема, потому что у нас есть обязательный переназначения конфигурационный файл в месте, которое вступает в силу во время выполнения:

<dependentAssembly> 
    <assemblyIdentity name="*B*" publicKeyToken="..." culture="neutral" /> 
    <bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="1.1.32.0" /> 
</dependentAssembly> 

Чтобы дать немного фона, то библиотеки DLL существуют в отдельных решениях, поэтому некоторые ссылки являются ссылками на файлы, а не ссылками на проекты, просто с чем мне нужно жить!

Есть ли эквивалентное перенаправление привязки, которое применяется во время компиляции?

Я попытался компиляции с помощью отладки библиотек DLL (версия 1.0.0.0), с источником откатывается к соответствующей версии выше, однако я получаю следующее сообщение об ошибке во время выполнения:

находящейся Ассамблеи манифеста определение не соответствует ссылке на сборку

возможно, сервер сборки настроен по-разному к моей машине, но в любом случае это не похоже на работу ...

+0

У вас есть свойство «Специфическая версия», равное true в вашей ссылке на сборку? (нажмите «свойства» в ссылке для проверки) –

+0

Нет, что установлено в false, проблема заключается в косвенных ссылках. – Lee

ответ

7

Я сомневаюсь, что это возможно " исправить "его, как вы хотите. Если вы прочитали документацию по этой ошибке компиляции (https://msdn.microsoft.com/en-us/library/416tef0c.aspx), вы увидите, что вы можете либо обновить код, чтобы использовать ту же версию, либо ссылаться на обе версии во время компиляции (а не вариант в вашем случае).

Представьте, что версия 1.0.0.0 содержит метод MyMethod(), но версия 1.0.0.1 содержит MyMethod (string), а первая версия используется сборкой A, вторая версия используется сборкой, которую вы компилируете. Как вы хотите, чтобы компилятор разрешил это? Во время выполнения, когда вы используете перенаправление привязки, будет загружена только одна версия. Здесь вы не являетесь владельцем кода для сборки A (который вы ссылаетесь и который в свою очередь ссылается на MyMethod), а ссылка на сборку 1.0.0.0 встроена в манифест А.

Короткий рассказ - я предполагаю, что только для его решения можно использовать сборку A, которая ссылается на ту же версию B, что и вы.

+0

Если бы была сборка A, которая ссылалась на ту же версию B, она больше не существует, это устаревшее приложение. Чтобы сделать то, что вы говорите, мне нужно будет разобрать и воссоздать A, при этом единственным изменением будет ссылка на версию B. Я правильно понял ваше решение? – Lee

+0

Кажется странным, что компилятор менее гибко связан с DLL, на который ссылаются, чем время выполнения – Lee

0

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

Однако вы здесь для решения проблемы, поэтому я сделаю предложение. Одним из возможных способов облегчить эту боль является упаковка каждого из ваших «отдельных DLL-решений» в NuGet packages. Вам не нужно публиковать их в галерее NuGet, вместо этого вы можете использовать специализированный фид NuGet (например, MyGet) или даже host your own. Как только у вас есть файлы в фиде, немного проще управлять получением правильной версии в проекте.

Основное преимущество использования NuGet является то, что вам не нужно, чтобы проверить двоичные файлы в систему управления версиями, так что они не будут выходить из синхронизации с номером версии, на который ссылается в файле .csproj или .vbproj. Если настроено с NuGet package restore, правая версия каждого из пакетов будет автоматически установлена ​​при компиляции и, таким образом, будет гарантирована построение того же самого пути, независимо от машины, которая ее строит.

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

Конечно, NuGet не идеален и требует немного усилий для настройки, и даже тогда у вас могут возникнуть проблемы с синхронизацией версий, но их обновление до нужной версии значительно проще.

0

Если вы правильно поняли, у вас есть устаревшая сборка A, которая ссылается на конкретную версию сборки B. В то же время вы строите служебную программу C, которая использует обе сборки - A и B.

Вы должны иметь возможность использовать две разные версии одной и той же сборки B, выполнив следующие шаги. Не компиляции Перенаправление время, но он должен работать:

  1. Добавить ссылку на сборку A к вашему проекту C установите SpecificVersion = true;
  2. Добавить ссылку на сборку B версия 1.1.39.0 на ваш проект C, комплект SpecificVersion = true;
  3. Создайте событие сборки, которое копирует версию 1.1.39.0 сборки B для вывода выходного тракта /bin/B_1.1.39.0/B.dll;
  4. Добавить следующие переадресации и указать произвольное местоположение для сборки B с версией 1.1.39.0 с использованием элемента codeBase;

Теперь ваше наследие сборки A должны быть счастливы, как у вас есть версия 1.1.32.0 сборки B в папке вывода. Ваша утилита C должна быть счастлива, как и она, используя определенную версию 1.1.39.0 сборки B, и вы указали нестандартное местоположение, где ее искать.

Надеюсь, это поможет!

3

Это очень распространенная ошибка. Пакеты Nuget являются наиболее вероятными нарушителями проблем, log4net и NewtonSoft.Json находятся на вершине этого списка. Современные версии MSBuild знают, как это решить. Что-то, что вы можете увидеть при использовании «Инструменты»> «Параметры»> «Проекты и решения»> «Сборка и запуск»> «Вывод сборки проекта MSBuild» verbosity = Подробно.

Я покажу, как он выглядит на VS2015, воспроизводя ваш точный проблемный сценарий.Он начинает становиться интересным в задаче ResolveAssemblyReference:

1>Task "ResolveAssemblyReference" 
... 
1> Primary reference "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null". 
1>  Resolved file path is "c:\projects2\BCopy\bin\Debug\B.dll". 
1>  Reference found at search path location "{HintPathFromItem}". 
1>  Found related file "c:\projects2\BCopy\bin\Debug\B.pdb". 
1>  The ImageRuntimeVersion for this reference is "v4.0.30319". 
1> Primary reference "A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null". 
1>  Resolved file path is "c:\projects2\A\bin\Debug\A.dll". 
1>  Reference found at search path location "{HintPathFromItem}". 
1>  Found related file "c:\projects2\A\bin\Debug\A.pdb". 
1>  The ImageRuntimeVersion for this reference is "v4.0.30319". 

И куча больше для .NET Framework сборок. К концу этой задачи он замечает, что А имеет зависимость от новой версии B:

1> Dependency "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null". 
1>  Resolved file path is "c:\projects2\B\bin\Debug\B.dll". 
1>  Reference found at search path location "c:\projects2\B\bin\Debug". 
1>   For SearchPath "c:\projects2\B\bin\Debug". 
1>   Considered "c:\projects2\B\bin\Debug\B.winmd", but it didn't exist. 
1>  Required by "A, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL". 
1>  Found related file "c:\projects2\B\bin\Debug\B.pdb". 
1>  This reference is not "CopyLocal" because it conflicted with another reference with the same name and lost the conflict. 
1>  The ImageRuntimeVersion for this reference is "v4.0.30319". 
1> There was a conflict between "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" and "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null". 
1>  "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" was chosen because it was primary and "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null" was not. 
1>  References which depend on "B, Version=1.1.32.0, Culture=neutral, PublicKeyToken=null" [c:\projects2\BCopy\bin\Debug\B.dll]. 
1>   c:\projects2\BCopy\bin\Debug\B.dll 
1>   Project file item includes which caused reference "c:\projects2\BCopy\bin\Debug\B.dll". 
1>    B, Version=1.1.39.0, Culture=neutral, processorArchitecture=MSIL 
1>  References which depend on "B, Version=1.1.39.0, Culture=neutral, PublicKeyToken=null" [c:\projects2\B\bin\Debug\B.dll]. 
1>   c:\projects2\A\bin\Debug\A.dll 
1>   Project file item includes which caused reference "c:\projects2\A\bin\Debug\A.dll". 
1>    A, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL 
1>Done executing task "ResolveAssemblyReference". 

Обратите внимание, как он пытается решить, следует ли использовать версию 1.1.32.0 или 1.1.39.0. Ему нравится старая версия лучше, поскольку она является «основной ссылкой». Другими словами, ваш проект ссылается на него, а значение 1.1.39.0 менее важно, поскольку оно является косвенной ссылкой от A.

Проект строит чистую, без жалобы. Почему это не работает для вас, совершенно неясно, довольно важно назвать вашу версию VS. Я точно не помню, когда эта функция была добавлена, это было давно. Где-то вокруг VS2010 или VS2012.

Итак, постарайтесь, чтобы сравнить трассировку сборки, которую вы получаете на своей машине, с тем, что я разместил. Если это просто простая старая версия VS-версии, то вы, конечно, будете намного опережать ее.

+0

Я не знал, что достаточно многословия, очень удобно! Я обязательно попробую, когда перейду к проблеме, я использую VS2013. Если это окажется возможным, я буду отмечать это как ответ, но пока я пойду с Evk, поскольку ссылка (ссылаясь на VS2015) является авторитетной. – Lee

0

Вы можете обойти ошибку компилятора, убедившись, что вы обертываете типы из сборки А так, чтобы они не были видны вне сборки B, тогда вы можете зависеть от сборки B, использовать от A до B и использовать bindingRedirect чтобы сборка A загрузила правильную версию DLL. Ваш пробег будет отличаться, но он работает.

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