Понимание действий .NET Core csproj - PullRequest
0 голосов
/ 15 января 2019

Я пытаюсь скопировать содержимое папки для создания вывода. В идеале по тому же пути относительно папки вывода / публикации. У меня есть:

<!-- front-end files to serve -->
<ItemGroup>
  <Folder Include="Frontend\Content">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Folder>
</ItemGroup>

Однако, когда я использую dotnet publish, файл не копируется.

Это работает для файла конфигурации, который я хочу - это было сгенерировано VS:

<ItemGroup>
  <None Remove="my-config.json" />
</ItemGroup>
<ItemGroup>
  <Content Include="my-config.json">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

Итак, мой вопрос - что это за сумасшествие? Семантически, элемент с именем None с атрибутом Remove - что это вообще значит?

Моя смутная интуиция состоит в том, что элемент эквивалентен «набору», содержимое которого будет действовать на основе имени этого элемента / набора, и что «Включить», «Исключить», «Удалить» каким-либо образом (?) Взаимодействуют для определения и уточните содержимое этого набора.

Но тогда - что такое "Папка"? Что такое «контент»? Что происходит, когда все удваивается: зачем нужна комбинация «Нет / Удалить»? Если это вообще так - это было сгенерировано VS!

По документации я нашел:

https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#how-to-see-the-whole-project-as-msbuild-sees-it,, в котором говорится о глобалах Compile, EmbeddedResource и None по умолчанию (глобусы «Включить, исключить и удалить»). Я знаю, что такое шарик, я знаю, что означают эти действия, но что это за шарики? Как они взаимодействуют?

Он также указывает на документацию MSBuild на https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-project-file-schema-reference?view=vs-2017,, но это кажется бесполезным для этого: он не документирует показанные элементы None, EmbeddedResource или Compile и не говорит о Content и Folder элементов, которые я нашел в других примерах (и сгенерированных VS).

На самом деле, ничего из того, что я нашел, не говорит о том, что все это значит.

Где я могу найти документацию для этого?

1 Ответ

0 голосов
/ 20 января 2019
  1. Папки

<Folder> используется внутри VS, просто показывает узел в обозревателе решений, например чтобы получить точку, щелкните правой кнопкой мыши «Добавить> Новый…». wwwroot является классическим примером для приложений ASP.NET Core, но если вы используете функцию VS «Добавить> Новая папка» или удаляете все файлы в существующей папке, он добавит узел, чтобы сохранить его в обозревателе решений. .

Элементы <Folder> не используются во время сборки. Копирование элементов определяется на основе метаданных, указанных для известных типов элементов (Нет, Содержимое, ...), а не на основе элементов папки в иерархии файловой системы.

Если вы хотите указать метаданные для всей иерархии, вы можете сделать

<Content Include="my/content/**/*" CopyToPublishDirectory="True" … />
  1. Включить / удалить комбо

Внутри статического содержимого файла проекта (не в <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" />
  1. Так что же делают эти вещи в <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 будет показывать элементы в обозревателе решений только для типов элементов, которые настроены таким образом. И для этих типов элементов имеет смысл не указывать файл в нескольких из них.

...