Я создал пакет NuGet , который генерирует код C # из файлов DSL во время проектирования и сборки.Он отлично работает в Visual Studio, но имеет некоторые проблемы в Rider (о которых я расскажу ниже).
В Visual Studio
Пакет объявляет пользовательских элементов для DSLфайлы и присваивает им метаданные MSBuild:Compile
Generator
, которые запускают сборку во время разработки в Visual Studio при каждом изменении файла.
Затем настраиваемая цель подключается кпостроить с BeforeTargets="CoreCompile"
.Он генерирует код C # и добавляет Compile
элементов в проект.Цель выполняется как в обычной, так и во время разработки, и поддерживает инкрементные сборки , чтобы избежать ненужной работы.
Вот соответствующий (упрощенный и прокомментированный) код MSBuild:
Файл props
:
<Project>
<!-- Define the item type with its default metadata -->
<ItemDefinitionGroup>
<ZebusMessages>
<Generator>MSBuild:Compile</Generator>
</ZebusMessages>
</ItemDefinitionGroup>
<!-- Make the item type user-visible in VS -->
<ItemGroup>
<AvailableItemName Include="ZebusMessages" />
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)ZebusMessages.xml" />
</ItemGroup>
<!-- Include all .msg files by default -->
<ItemGroup>
<ZebusMessages Include="**\*.msg" Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder)" />
</ItemGroup>
</Project>
Файл targets
:
<Project>
<ItemGroup>
<!-- Add a GeneratorTargetPath metadata for the target file -->
<ZebusMessages Update="@(ZebusMessages)" GeneratorTargetPath="$([MSBuild]::ValueOrDefault('$(IntermediateOutputPath)ZebusMessages/%(RecursiveDir)%(FileName)%(Extension).cs', '').Replace('\', '/'))" />
<!-- Remove all None items for .msg files -->
<None Remove="**\*.msg" />
</ItemGroup>
<Target Name="GenerateZebusMessages"
BeforeTargets="CoreCompile"
Condition="'@(ZebusMessages)' != ''"
Inputs="@(ZebusMessages)"
Outputs="@(ZebusMessages->'%(GeneratorTargetPath)')">
<!-- Generate output files -->
<GenerateZebusMessagesTask InputFiles="@(ZebusMessages)" />
<ItemGroup>
<!-- Add the output items -->
<Compile Include="@(ZebusMessages->'%(GeneratorTargetPath)')" Visible="false" />
<FileWrites Include="@(ZebusMessages->'%(GeneratorTargetPath)')" />
</ItemGroup>
</Target>
</Project>
Полные файлы доступны здесь .
InRider
Протестировано с Rider 2018.3.3:
Это не сработало из коробки в Rider, так как похоже, что оно не запускает сборки во время разработки, как VS.
Сначала Rider полностью не знал о сгенерированных файлах C #, из-за чего он отображал ошибки в коде, который ссылается на сгенерированные классы.
Я использовал внутренний режим Rider , который предоставляетдействие «Обновить проект и показать журналы» в проекте, которое показывает, что Rider вызывает MSBuild при загрузке проекта со следующими целями:
GenerateAssemblyInfo; _CheckForInvalidConfigurationAndPlatform; GetFrameworkPaths; ResolvePackageDependenciesDesignTime; CollectPackageReferences; BeforeResolveReferences; ResolveAssemblyReferences; ResolveComReferences; ResolveSDKReferences; ResolveCodeAnalysisRuleSet
Обратите внимание на отсутствие CompileDesignTime
или Compile
в этом списке.
* 1054 добавлено к этой цели. *1053* * 1054support Rider:
<Target Name="GenerateZebusMessagesRiderDesignTime"
Condition="'$(BuildingByReSharper)' == 'true'"
AfterTargets="PrepareForBuild"
DependsOnTargets="GenerateZebusMessages" />
Перехватывает PrepareForBuild
, от которого зависит ResolveAssemblyReferences
, и вызывает GenerateZebusMessages
.
. Это позволяет Rider знать о сгенерированных файлах, но есть проблемыЯ хотел бы решить:
- Если я отредактирую MSG-файл, сгенерированный код C # будет обновлен только при сборке проекта, а завершение кода Rider не обновится до тех пор.
- Если я добавлю MSG-файл в проект, мне нужно перезагрузить проект, чтобы он был учтен.Построение проекта здесь не помогает.
Вопрос
Я бы хотел, чтобы Rider вызывал цель MSBuild и переоценивал проект всякий раз, когда MSG-файл редактируется или добавляется./removed.
При добавлении файла я нашел только следующее в журналах, но это мало помогает:
10:54:05.076 |I| ProjectModel | RequestBuilder thread:7 | Add item ZebusMessages = 'OtherFile.msg'...
10:54:05.076 |I| ProjectModel | RequestBuilder thread:7 | Item matches to a wildcard pattern, mark project as dirty
10:54:05.095 |I| ProjectModel | RequestBuilder thread:7 | Project file content requested: ZebusMessages.csproj
10:54:08.330 |I| ProjectModel | RequestBuilder thread:7 | Item with EvaluatedInclude 'OtherFile.msg' was already changed. Perform project reevaluation before processing.
10:54:08.361 |I| ProjectModel | RequestBuilder thread:7 | Project 'ZebusMessages.csproj' was reevaluated in 22 ms, EvaluationCounter: 9
Ничто другое не упоминает MSBuild в этот период времени в журналах.
Можно ли вызвать что-то похожее на сборку во время разработки в Rider при изменении данного типа файла?
Или в более общем случае, при каких обстоятельствах Rider вызывает MSBuild для переоценки проекта