В чем разница между «без включения» и «без обновления» в проектах csproj в стиле SDK? - PullRequest
2 голосов
/ 28 октября 2019

Я искал правильный способ убедиться, что appsettings.json копируется в каталог bin при сборке моего проекта.

В этой статье рекомендуется использовать "none update"

<ItemGroup>
    <None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

И этот ответ на стекопоток рекомендует использовать "none include":

<ItemGroup>
    <None Include="appsettings.json" CopyToOutputDirectory="Always" />
</ItemGroup>

В чем разница между update и include?

1 Ответ

1 голос
/ 29 октября 2019

В чем разница между обновлением и включением?

Согласно этому документу :

Использование :

Include attribute => Файл или подстановочный знак для включения в список элементов.

Update attribute => Позволяет изменять метаданные файла, включенного с помощью глобуса. .

Рабочая область:

Include attribute:

1. Работает для обоих normal .net framewrok (не в формате SDK), .net core and .net standard(формат SDK), также проекты C ++ ...

2.Используется во многих версиях VS (как я знаю, от VS2010 до VS2019)

3. Include работает даже в ItemGroup в Цели

Update attribute:

1. Работы для основных проектов .net

2. Доступно в VS2017 и более поздних версиях

3.Не поддерживается при использовании в ItemGroup внутри Target

Тесты и результаты:

Первый тест, когда c.txt не включен:

  <ItemGroup>
    <DoSth Include="a.txt"/>
    <DoSth Include="b.txt"/>
    <DoSth Update="c.txt" Metadata="test"/>
  </ItemGroup>

  <Target Name="MyTest" AfterTargets="build">
    <Message Text="@(DoSth)" Importance="high"/>
  </Target>
  <!--The output is a.txt and b.txt, no c.txt.-->

Второй тест, когда включен c.txt:

  <ItemGroup>
    <DoSth Include="a.txt"/>
    <DoSth Include="b.txt"/>
    <DoSth Include="c.txt" Metadata="original"/>
    <DoSth Update="c.txt" Metadata="test"/>
  </ItemGroup>

  <Target Name="MyTest" AfterTargets="build">
    <Message Text="@(DoSth)" Importance="high"/> <!--The output files are a.txt,b.txt and c.txt.-->
    <Message Text="%(DoSth.Identity)+%(DoSth.Metadata)" Importance="high"/>  <!--The output Metadata of c.txt is test instead of original-->
  </Target>

Так что этоОчевидно, что Update attribute используется только для обновления метаданных одного элемента. У него нет функции включения некоторых файлов. И он будет работать только тогда, когда один файл был включен в один элемент.

Чтобы уточнить что-то при использовании Update + appsettings.json в .net core консоли и asp.net core веб-приложении:

В основном веб-приложении Asp.net:

Если вы создаете новый проект asp.net core web, вы можете увидеть файл appsettings.json в обозревателе решений. по умолчанию. Но если вы читаете xx.csproj, вы не можете найти определение там, определения явно не отображаются в xx.csproj для формата sdk.

В этой ситуации, если мы используем скрипт как<None Include="appsettings.json" CopyToOutputDirectory="Always" />, он всегда работает, чтобы скопировать этот файл на выход.

Но для сценария <None Update="appsettings.json" CopyToOutputDirectory="PreserveNewest" /> он работает только тогда, когда в файле проекта нет операторов типа <Content xxx="appsettings.json"...>.

И я рекомендую вам сделать это с помощью пользовательского интерфейса VS вместо ручного редактирования xx.csproj. Мы можем изменить Build Action and Copy To Output Настройки в Property Window:

enter image description here

Если мы установим build action равным None, и скопировать вВывод будет Copy if Never из Copy Always, в xx.csproj мы можем найти:

  <ItemGroup>
    <Content Remove="appsettings.json" />
  </ItemGroup>

  <ItemGroup>
    <None Include="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

Так что VS использует None + Include для этого. В соответствии со всем вышеизложенным, я предлагаю вам использовать None+Include вместо None+Update в вашем проекте. Кроме того, наиболее рекомендуемый способ - управлять поведением копирования с помощью пользовательского интерфейса в VS IDE вместо ручного редактирования. Надеюсь, что все вышеперечисленное поможет:)

Update1:

Мы можем добавить этот скрипт в файл проекта для вывода информации о None Items и Content Items, которые не показаны в csproj:

  <Target Name="TrytoFindDefinitionsNowShown" AfterTargets="build">
    <Message Text="None: @(None)" Importance="high"/>
    <Message Text="Content: @(Content)" Importance="high"/>
  </Target>

Update2:

Я только что провел несколько тестов и обнаружил даже в консольном проекте ядра .net в VS, хотя в csproj нет определений, обновление может работать,Странный?

И наконец я обнаружил, что это потому, что это определение скрыто или не отображается в файле csproj, фактически, когда у вас есть файл appsettings.json в проекте, у вас уже есть <None Include="appsettings.json"... определено (иногда Content + include, ikt зависит от того, как вы добавляете этот файл), хотя это не подходит для просмотра в csproj, см. мой скриншот:

enter image description here

Так вот почему Update может работать с поведением копирования, хотя это то, что используется для изменения метаданных. Прежде чем использовать обновление, уже существует определение None+Include+Appsettings.json, хотя оно не показано в csproj. (Для формата SDK)

Update3:

Я внес небольшие изменения в скрипт в Update1 для отображения метаданных <None Include="appsettings.json">.

enter image description here

Таким образом, в проекте консоли ядра .net файл appsettings.json по умолчанию равен

<None Include="appsettings.json" CopyToOutputDirectory="Never" /> 

Именно поэтому None+Include+Always (перезаписать) иNone+Update+Always or PreserveNewest (Изменить метаданные) работают для поведения копирования. И он может объяснить, почему по умолчанию этот файл не будет скопирован, даже если VS где-то скрыл определения None+Include. Поскольку CopyToOutputDirectory по умолчанию установлено как Никогда.

...