Подтвердить что ты не робот

Правила копирования ссылочных сборок

Какие правила выполняет VS (msbuild?) во время сборки решения? В каких случаях он копирует косвенные ссылки на выходные папки и в которых нет?

4b9b3361

Ответ 1

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

  • MainProgram: консольное приложение с прямой ссылкой на DirectAssembly. Код в главном:

    var foo = new DirectAssembly.SampleClass();
    
  • DirectAssembly: библиотека классов с прямой ссылкой на IndirectAssembly. Содержит SampleClass:

    public class SampleClass
    {
        // Comment out this line to change the behaviour...
        IndirectAssembly.IndirectClass neverUsed = null;
    
        public SampleClass()
        {
            object x = Activator.CreateInstance("IndirectAssembly",
                                                "IndirectAssembly.IndirectClass");
    
        }
    }
    
  • IndirectAssembly: содержит открытый класс IndirectClass с открытым конструктором без параметров

Как описано выше, он работает, потому что IndirectAssembly копируется в выходную папку MainProgram. Если вы прокомментируете строку, указанную в SampleClass, IndirectAssembly не копируется (даже если она все еще является ссылкой), и код не будет работать во время выполнения.

Я не говорю, что это все правила, но они, по крайней мере, начинаются...

Ответ 2

Есть тонкость, которая не рассматривается в предыдущих ответах, а именно, является ли ссылка на сборку в GAC.

Рассмотрим проект, который ссылается на сборку A, которая, в свою очередь, зависит от сборок B и C. Сборка C, как оказалось, была установлена ​​в GAC каким-то "другим продуктом". Я обнаружил, что Visual Studio 2013 копирует A и B, но не C, в выходную папку, потому что C уже находится в GAC. Если я затем запустил приложение на компьютере, на котором не установлено "другое изделие", я получаю отказ от выполнения во время выполнения.

Я также заметил, что документация Microsoft в этой области кажется неправильной, по крайней мере для VS2013.

Управление списками проектов:

Если вы развертываете приложение, содержащее ссылку на пользовательский компонент, зарегистрированный в GAC, компонент не будет развернут вместе с приложением независимо от параметра CopyLocal. В более ранних версиях Visual Studio вы можете установить свойство CopyLocal для ссылки, чтобы убедиться, что сборка была развернута. Теперь вы должны вручную добавить сборку в папку \Bin

Мои тесты с VS2013 показывают, что в отличие от выше, CopyLocal = True всегда копирует сборку с прямой ссылкой в ​​выходную папку, независимо от того, находится ли она в GAC. Но косвенные ссылочные сборки, по-видимому, копируются только в том случае, если они не находятся в GAC.

Такое поведение означает, что для того, чтобы с помощью приложения были установлены косвенные ссылки, вы должны добавить явные ссылки на них, с CopyLocal = True (или вручную скопировать их). Обратите внимание, что по умолчанию CopyLocal будет установлено значение False, если сборка находится в GAC.

Ответ 3

Он должен скопировать все рекурсивные ссылки. Например:

enter image description here

--- EDIT ---

Правила (по крайней мере, в VS2010) выглядят следующим образом:

  • Косвенная ссылка копируется только при фактическом использовании.
  • Прямая ссылка копируется независимо от того, даже если она не используется.

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

Отвлечение внимания в стороне, кажется, достаточно, чтобы просто добавить минимальный набор ссылок на каждом уровне иерархии проекта.

Ответ 4

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

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

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

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