Возможно ли конфликт между двумя библиотеками DLL, не позволяющий создать решение

9

Хотя у меня есть конкретный случай, но меня интересует общая ситуация.

Могут ли две библиотеки DLL, добавленные в качестве ссылки на проект Visual C #, сталкиваться друг с другом, чтобы помешать созданию решения? Если это так, каковы возможные пути смягчения этого.

Шамим Хафиз
источник

Ответы:

13

Это очень возможно.

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

Если вы уверены, что у вас есть уникальные пространства имен, как и ваши ссылки, у вас не будет этой проблемы.

Другая возможность связана с различными версиями зависимости - если ваш проект использует (например) библиотеку журналов версии 1.2, но добавленная сборка имеет зависимость от той же сборки, но с другой версией (скажем, 1.3) и любым вашим проектом. или добавленная сборка была сконфигурирована / построена для использования определенной версии, вы получите конфликт, и сборка не удастся.

Обе эти проблемы могут быть решены с помощью псевдонимов сборки, как описано здесь .

Одед
источник
Я не совсем уверен, что это правда. Если вы посмотрите на CIL, то CLR ссылается на символы, явно находящиеся в определенных сборках, с обозначением [сборка] перед каждым символом. Возможно, что компилятор C # навязывает эту проблему, но я не думаю, что это ограничение платформы.
Ям Маркович
@Yam Marcovic, как компилятор определит, какое пространство имен вы пытаетесь использовать в определенном классе? Полностью определенные конфликты имен классов определенно предотвратят сборку.
Джереми
Компилятор C # предоставляет вам опцию для псевдонимов сборок, когда имеешь дело со сборками с одинаковыми именами (и, возможно, с такими же символами, определенными в них). См. Stackoverflow.com/questions/517058/…
Ям Маркович
@Yam - Правда, однако, вам нужно знать об этом флаге и использовать его. Простое добавление сборки нарушит сборку.
Одед
1
Очевидно. Вот почему он приходит сюда за помощью, правда? Он хочет знать об этом флаге и использовать его, потому что он даст ему более чистое решение, не затрагивая его проект или сторонние утилиты.
Ям Маркович
4

Поскольку никто не упомянул об этом, вы спросили:

Каковы возможные способы смягчить это

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

Посмотрите на http://blogs.msdn.com/b/ansonh/archive/2006/09/27/774692.aspx

Ям Маркович
источник
3

Да, это очень возможно.
Допустим, вы добавили ссылку на некоторую DLL, которая использует старую версию Lucene.Net, и вы хотите включить последнюю версию.
Вы можете решить эту проблему, используя внешние псевдонимы: http://msdn.microsoft.com/en-us/library/ms173212.aspx

šljaker
источник
+1 это, кажется, правильный ответ, не как насчет "внешнего" псевдонима.
Джалайн
1

Вы можете поместить столько разных версий сборки, сколько хотите, в глобальный кэш сборок при условии, что они имеют строгое имя. Это может помочь вам, если вы хотите, чтобы разные приложения использовали разные версии сборки машинным способом. Однако использование разных версий сборки в ОДНОМ приложении по-прежнему вызовет проблемы.

По какой причине вам нужны обе версии одновременно?

Jalayn
источник
1
Ну, я не добавляю явно разные версии. В основном у меня есть приложение WPF. Теперь, чтобы добавить стороннюю функцию, я добавил несколько библиотек DLL, и именно эти библиотеки DLL могут быть в конфликте.
Шамим Хафиз
1
Хорошо, тогда вы можете добавить эти сторонние DLL в GAC? Прошло много времени с тех пор, как я читал об этих вещах, но я подозреваю, что это может решить вашу проблему.
Джалайн
Что подразумевается под GAC здесь?
Шамим Хафиз
1
Глобальный кэш сборок, см. Msdn.microsoft.com/en-us/library/yf1d93sz%28v=vs.71%29.aspx
Jalayn
0

Точно. Вы можете получить ошибку компилятора «Неоднозначная ссылка», когда два объекта невозможно различить. Как правило, вы можете указать полный путь в коде, и это не вызовет проблемы, но если dll были полностью идентичны, то вы не сможете различить два объекта в любом случае. Ся у нас есть две dll:

System.IO, который содержит класс File

а также

MyProject.IO, который содержит класс File

Если бы у вас было что-то подобное ...

using System.IO;
using MyProject.IO;

...
private void foo()
{
    File f = new File();
}

... у вас была бы неоднозначная ссылка, так как невозможно определить, о каком файле вы говорите. Это исправит это:

using System.IO;
using MyProject.IO;

...
private void foo()
{
    MyProject.IO.File f = new MyProject.IO.File();
}

Единственный способ, который было бы трудно исправить, состоял бы в том, что бы путь «File» был идентичен в обеих сборках, но это потребовало бы маловероятной ситуации, когда два dll имели одинаковую структуру пространства имен. Например, моя описанная выше ситуация никогда бы не произошла, поскольку никто не будет называть там проект «Система» (за исключением реальных разработчиков .Net Framework).

Морган Херлокер
источник
На самом деле это часто случается, если вы создаете решения на основе популярных сторонних библиотек. Например, библиотеки Twitter могут зависеть от старой версии вашей json lib
Hoàng Long