- Папки
<Folder>
используется внутри VS, просто показывает узел в обозревателе решений, например чтобы получить точку, щелкните правой кнопкой мыши «Добавить> Новый…». wwwroot
является классическим примером для приложений ASP.NET Core, но если вы используете функцию VS «Добавить> Новая папка» или удаляете все файлы в существующей папке, он добавит узел, чтобы сохранить его в обозревателе решений. .
Элементы <Folder>
не используются во время сборки. Копирование элементов определяется на основе метаданных, указанных для известных типов элементов (Нет, Содержимое, ...), а не на основе элементов папки в иерархии файловой системы.
Если вы хотите указать метаданные для всей иерархии, вы можете сделать
<Content Include="my/content/**/*" CopyToPublishDirectory="True" … />
- Включить / удалить комбо
Внутри статического содержимого файла проекта (не в <Target>
- там применяются несколько различных правил), MSBuild позволяет три операции над коллекциями элементов:
- Включить: добавление элементов в «коллекцию» предметов указанного типа
- Обновление: изменение метаданных для элементов указанного типа элементов
- Удалить: удалить элементы из "" коллекции ""
Это означает, что если вы сделаете
<None Include="foo.txt" />
<Content Include="foo.txt" />
Тогда и коллекции @(None)
, и @(Content)
будут содержать foo.txt
. На самом деле это не проблема для системы сборки (если вы не укажете, что они оба должны быть скопированы в вывод - это приводит к ошибкам с конфликтующими путями вывода), но для инструмента, который показывает вам файлы в вашем проекте и их свойства, это может создавать сложные ситуации.
Если foo.txt
указан как None
, Content
и EmbeddedResource
, то инструмент IDE (VS, Rider, VS / Mac, ...) должен принять сложное решение о том, что вам показать для этого файл.
Чтобы смягчить эту проблему, хорошо убедиться, что файл указан как один из этих типов элементов «Build Action», чтобы не допустить путаницы в среде IDE (и транзитивно также для пользователя).
Так почему же нужно удалять файлы из None
?
Новые проекты "SDK-style" добавляют множество настроек по умолчанию. Они в основном содержат что-то вроде (упрощенно !!):
<None Include="**/*" />
Поэтому, если вы хотите изменить файл на встроенный ресурс или элемент контента, вы должны удалить файл из коллекции @(None)
.
Если вам не нужно менять тип элемента, вы также можете использовать Update
:
<None Update="some/content/**/*" CopyToOutputDirectory="True" />
- Так что же делают эти вещи в
<ItemGroup>
?
Эти определения ничего не делают сами по себе. Они просто заполняют / меняют коллекцию «предметов».
Вы даже можете создать свои собственные и использовать их позже:
<MyCoolFiles Include="cool/files/**/*;other/cool/files/**/*" />
<None Remove="@(MyCoolFiles)" />
<Content Include="@(MyCoolFiles)" CopyToPublishDirectory="True" />
<Target Name="PrintCoolFiles" BeforeTargets="BeforeBuild">
<Message Importance="high" Text="These are my cool files: @(MyCoolFiles)" />
</Target>
Ключевым моментом является то, что некоторые части логики сборки ищут элементы, о которых они знают, и используют их.
Часть, которая вычисляет входные данные для компилятора, будет искать элементы Compile
и EmbeddedResource
, часть, которая определяет, какие файлы для копирования в каталог вывода, будет искать различные элементы (None
, Content
, EmbeddedResource
и несколько других IIRC) с определенным набором метаданных.
Новые типы проектов могут определять свои собственные типы элементов, которые будут перечислены в обозревателе решений VS через точки расширения.
Но VS будет показывать элементы в обозревателе решений только для типов элементов, которые настроены таким образом. И для этих типов элементов имеет смысл не указывать файл в нескольких из них.