Ошибка 2 Тип ‹T› существует как в ILMerge

У меня есть 3 проекта:

  • A_MainProject (стартовый проект)
  • B_IntermediateProject
  • C_SharedClassLibrary

Зависимости:

А зависит от В и С

В зависит от С

и C зависит только от системы.

У каждого проекта есть собственное пространство имен.

Пока ILMerge не установлен, все работает нормально.

Если ILMerge активирован для проекта A ("A_MainProject"), все по-прежнему работает нормально, и создается один автономный исполняемый файл для проекта A.

Если ILMerge теперь также активирован для B_IntermediateProject, я получаю следующую ошибку:

Error   2   The type 'C_SharedClassLibrary.SharedClass' exists in both 'c:\dev\ILMergeError\B_IntermediateProject\bin\Debug\B_IntermediateProject.exe' and 'c:\dev\ILMergeError\C_SharedClassLibrary\bin\Debug\C_SharedClassLibrary.dll'    C:\dev\ILMergeError\A_MainProject\Program.cs    12  A_MainProject

Я использую «задачу MSBuild ILMerge» 1.0.3-rc2 с «ILMerge» 2.13.0307 (от mbarnett).

Минимальное решение содержит 3 проекта по одному классу в каждом. В этой версии ILMerge активирован только для одного проекта и работает:

ILMergeError_stillworking.zip

В этой версии он также активирован в проекте B и выдает ошибку:

ILMergeError_error.zip

Если я объединяю два исполняемых файла и dll с помощью ILMerge извне (ILMergeGUI), все работает нормально.

Заранее спасибо за ответ, Ксан-Кун.


person Xan-Kun Clark-Davis    schedule 22.04.2015    source источник
comment
на первый взгляд звучит как проблема с пространством имен.   -  person MethodMan    schedule 22.04.2015
comment
Здравствуйте и спасибо за ответ. Это уже 2 дня не дает мне покоя. Пожалуйста, позвольте мне объяснить, я пришел из Java, и концепция пакетов, кажется, немного отличается от пространства имен. Не могли бы вы объяснить немного больше, что вы имеете в виду? Должны ли все классы находиться в одном пространстве имен?   -  person Xan-Kun Clark-Davis    schedule 22.04.2015
comment
Нет, они не должны находиться в одном и том же пространстве имен и, возможно, не должны.   -  person doogle    schedule 22.04.2015
comment
Они не должны быть такими, но если у вас случайно есть имя метода, которое совпадает, например, с некоторыми из Microsoft.Interop, например, слово Application может вызвать то, что известно как столкновение методов, поэтому вам придется полностью квалифицировать метод по имени класса . имя метода имеет смысл, или, поскольку у вас есть AnotherMessageBox во всех 3, вам придется полностью квалифицировать его по его пространству имен, было бы неплохо увидеть некоторый код в заголовке .cs, как все 3 определены   -  person MethodMan    schedule 22.04.2015
comment
Я ужасно извиняюсь за поздний ответ и должен подготовить образец решения, чтобы продемонстрировать проблему. Тем временем у меня было больше информации, и я также опубликую некоторую информацию.   -  person Xan-Kun Clark-Davis    schedule 24.04.2015
comment
К сожалению, такая ситуация особенно часто возникает с тестом (MSTest). Если я использую ILMerge в любом из своих проектов, я должен сначала выгрузить все проекты тестирования. Это нормально?   -  person Xan-Kun Clark-Davis    schedule 28.04.2015
comment
Я думаю, что установка GLuck абсолютно верна, я переработал процесс сборки и теперь использую правильные сценарии сборки. Это все еще сложно, но намного лучше, чем раньше, когда мне также приходилось каждый раз переключать стартовый проект. Теперь есть одна сборка, и она создает нужные исполняемые файлы (все).   -  person Xan-Kun Clark-Davis    schedule 27.05.2015
comment
Я предлагаю вам также взглянуть на это Тип существует в обеих DLL   -  person Mohfath    schedule 21.11.2018
comment
Спасибо! На самом деле упоминаются некоторые интересные обходные пути, такие как настройка пользовательского псевдонима.   -  person Xan-Kun Clark-Davis    schedule 22.11.2018


Ответы (1)


Короткий ответ заключается в том, что вы должны включать ILMerge только для A, где он объединит оба A + B + C вместе.

Причина, по которой вы столкнулись с этой ошибкой, заключается в том, что когда вы включаете ILMerge на B, B также будет переупакован со всеми типами C (B' = B+C). Следовательно, когда ILMerge срабатывает для A, он объединяет A+B'+C = A+(B+C)+C.

Теперь может произойти 2 сценария:

  1. B использует C внутренне и не раскрывает (публично) какой-либо тип C (например, в качестве аргумента метода или возвращаемого значения). В этом случае вы можете заставить его работать с помощью параметров ILMerge (/internalize для B и /allowDup для A), хотя вы получите дважды каждый тип C в объединенной сборке A.

  2. B предоставляет типы C, которые могут использоваться A. В этом случае, даже если вам удастся заставить слияние работать, во время выполнения произойдет сбой, потому что A и B' ссылаются на разные типы (например, для класса c ссылки B' B'.c и A ссылаются на C.c), и вы получите неприятные исключения приведения типов, потому что это 2 разных типа (одно и то же имя, одно и то же пространство имен, но разные сборки).

(Они неприятны, потому что не указывают на несоответствие сборки, а исключение говорит только о том, что «c нельзя преобразовать в c», что многих может сбить с толку)

person Gluck    schedule 03.05.2015
comment
Привет! Я принял ваш ответ, поскольку он кажется наиболее верным. Хотя я так и не разобрался в сути проблемы, ваше первое предложение, безусловно, верно, и если возникает необходимость во втором (или более) exe-файлах, весь процесс сборки в любом случае должен быть хорошо спроектирован, чтобы именно эти ситуации не возникали. возникают. - person Xan-Kun Clark-Davis; 27.05.2015