Существует ли надежный (даже стандартизированный) подход к созданию библиотеки .NET, поддерживающей несколько целевых платформ одновременно?

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

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

Итак, представьте, что я пишу библиотеку C# MyLib (которую я бы назвал «продуктом»), которая компилируется в файл MyLib.dll. Я хочу поддерживать различные диапазоны целевых платформ: net35, net40, net45, netstandard1.2 и т. д. Поэтому я создаю сборки (файлы MSBuild или csproj) для каждой целевой платформы и объединяю их вместе в один пакет nuget, соблюдая рекомендации Nuget по структуре папок lib. Таким образом, продукт можно получить из одного артефакта сборки — пакета nuget.

Для каждой целевой версии фреймворка я стараюсь использовать ее функции и преимущества и предоставлять полные заполнения для более низких версий или удалять некоторые функции. В общем, дело в том, что «продукт» можно использовать независимо от целевой структуры проекта-потребителя - я имею в виду, что пакет nuget для MyLib должен быть установлен правильно, и следует ссылаться на соответствующую dll.

Итак, возникает несколько вопросов:

  • Правильно ли использовать одну и ту же информацию о версии сборки для разных сборок? Как повторное использование одного и того же файла AssemblyInfo.cs?
  • Какие атрибуты сборки не должны быть общими для моих сборок? Я начал другой поток в отношении атрибута [assembly: Guid("...")]]. Другие люди также отображают проблемы атрибута [assembly: AssemblyTitle("...")], но в другом контекст.
  • Есть ли хороший или стандартизированный подход к организации решения для поддержки описанного выше результата сборки. Действительно ли большинство проектов действительно заботятся о себе в достижении этого?

Мой собственный путь до сих пор состоит в том, чтобы использовать отдельный файл .csproj для каждой целевой платформы для одного и того же «продукта», но по мере развития разработки может стать утомительным поддерживать несколько проектов, даже если количество целевых платформ сейчас довольно значительно.


person Ivaylo Slavov    schedule 11.05.2017    source источник


Ответы (1)


Поэтому я создаю сборки (файлы MSBuild или csproj) для каждой целевой платформы и объединяю их в один пакет nuget.

Если вы используете новый формат csproj «SDK» из Visual Studio 2017, вам даже не нужно этого делать — он поддерживает несколько целевых платформ. Например:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   <TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
  </PropertyGroup>
</Project>

Этот проект поддерживает как .NET Framework 4.5.1, так и NETStandard1.3.

Это автоматически создает символы условной компиляции, поэтому вы можете делать такие вещи, как #if NET451 или #if NETSTANDARD1_3, чтобы вы могли условно применять код, если это необходимо. Вы также можете сделать это в самом .csproj для включения пакетов nuget только для одной платформы. Пример этого есть в проекте Dapper. CSPROJ-файл.

Используя новый dotnet cli, вы можете использовать dotnet pack, чтобы упаковать все это в пакет nuget.

person vcsjones    schedule 11.05.2017
comment
Хороший! Я уже использовал подобную вещь для разновидностей .netstandard в своих проектах, но неправильно - один файл csproj для каждой структуры. Хорошо ли это работает для старых версий фреймворка, поскольку я все еще поддерживаю net35? Кроме того, у меня возникли проблемы с импортом внешних целей msbuild, некоторые группы свойств не будут соблюдаться, если я не добавлю Sdk="Microsoft.NET.Sdk" в корневой элемент импортированной цели. Последнее вызывает предупреждения MSBuild. Есть ли у вас какие-либо рекомендации для этого? - person Ivaylo Slavov; 11.05.2017
comment
@IvayloSlavov Вы можете условно включать на основе фреймворка и даже делиться включениями между файлами csproj, используя файл реквизита. См. Directory.build.props и Dapper.sln. - person Dustin Kingen; 11.05.2017
comment
1. Конечно, это работает даже с .NET 2.0. JSON.NET имеет чрезвычайно подробный пример поддержки множества платформ. 2) позвольте мне взглянуть на это. - person vcsjones; 11.05.2017