Перенос библиотек .NET Framework в .NET CorePort .NET Framework libraries to .NET Core

Узнайте, как перенести код библиотеки .NET Framework в .NET Core, чтобы выполнять его на разных платформах и расширить диапазон использующих его приложений.Learn how to port .NET Framework library code to .NET Core, to run cross-platform and expand the reach of the apps that use it.

Предварительные требованияPrerequisites

В этой статье предполагается, что вы:This article assumes that you:

Стоит также ознакомиться со следующими статьями:You should also become familiar with the content of the following topics:

.NET Standard\.NET Standard\ В этой статье рассматривается официальная спецификация API-интерфейсов .NET, которые должны быть доступны во всех реализациях .NET.This topic describes the formal specification of .NET APIs that are intended to be available on all .NET implementations.

Пакеты, метапакеты и платформы Packages, Metapackages and Frameworks
Из этой статьи вы узнаете, как .NET Core определяет и использует пакеты и как пакеты поддерживают выполнение кода во множестве реализаций .NET.This article discusses how .NET Core defines and uses packages and how packages support code running on multiple .NET implementations.

Разработка библиотек с помощью кроссплатформенных средств Developing Libraries with Cross Platform Tools
В этой статье объясняется создание библиотек для .NET с помощью кроссплатформенных средств интерфейса командной строки.This topic explains how to write libraries for .NET using cross-platform CLI tools.

Дополнения к формату CSPROJ для .NET Core Additions to the csproj format for .NET Core
В этой статье перечислены изменения, внесенные в файлы проекта при перемещении в CSPROJ и MSBuild.This article outlines the changes that were added to the project file as part of the move to csproj and MSBuild.

Перенос кода в .NET Core — анализ зависимостей сторонних разработчиков Porting to .NET Core - Analyzing your Third-Party Party Dependencies
В этом разделе рассматривается переносимость зависимостей сторонних разработчиков и объясняется, что делать, если зависимость пакета NuGet не работает в .NET Core.This topic discusses the portability of third-party dependencies and what to do when a NuGet package dependency doesn't run on .NET Core.

Изменение целевой платформы для кода .NET Framework на .NET Framework 4.7.2Retargeting your .NET Framework code to .NET Framework 4.7.2

Если ваш код не предназначен для .NET Framework 4.7.2, рекомендуем изменить его целевую платформу на эту версию.If your code isn't targeting .NET Framework 4.7.2, we recommended that you retarget to .NET Framework 4.7.2. Это обеспечит доступность альтернативных API-интерфейсов последних версий в случаях, когда .NET Standard не поддерживает существующие API-интерфейсы.This ensures the availability of the latest API alternatives for cases where the .NET Standard doesn't support existing APIs.

Для каждого проекта в Visual Studio, который нужно перенести, выполните указанные ниже действия:For each of your projects in Visual Studio you wish to port, do the following:

  1. Щелкните проект правой кнопкой мыши и выберите пункт Свойства.Right-click on the project and select Properties.
  2. В раскрывающемся списке Требуемая версия .NET Framework выберите значение .NET Framework 4.7.2.In the Target Framework dropdown, select .NET Framework 4.7.2.
  3. Перекомпилируйте проекты.Recompile your projects.

Так как ваши проекты теперь предназначены для .NET Framework 4.7.2, используйте эту версию .NET Framework в качестве основы для переноса кода.Because your projects now target .NET Framework 4.7.2, use that version of the .NET Framework as your base for porting code.

Определение переносимости кодаDetermining the portability of your code

Следующий шаг — запуск анализатора переносимости API (ApiPort) для создания отчета о переносимости и его анализа.The next step is to run the API Portability Analyzer (ApiPort) to generate a portability report for analysis.

Для работы с .NET Core вам потребуются навыки использования ApiPort и создания отчетов о переносимости.Make sure you understand the API Portability Analyzer (ApiPort) and how to generate portability reports for targeting .NET Core. Процедура зависит от ваших потребностей и личных предпочтений.How you do this likely varies based on your needs and personal tastes. Ниже описано несколько подходов.What follows are a few different approaches. Вы можете использовать их в различных сочетаниях в зависимости от структуры кода.You may find yourself mixing steps of these approaches depending on how your code is structured.

Работа в первую очередь с компиляторомDealing primarily with the compiler

Такой подход может быть оптимальным для небольших проектов или проектов, в которых используется небольшое количество интерфейсов API .NET Framework.This approach may be the best for small projects or projects which don't use many .NET Framework APIs. Этот подход прост:The approach is simple:

  1. При необходимости запустите средство ApiPort для проекта.Optionally, run ApiPort on your project. Если вы запустили ApiPort, проверьте, нет ли проблем с отчетом, которые необходимо устранить.If you run ApiPort, gain knowledge from the report on issues you'll need to address.
  2. Скопируйте весь код в новый проект .NET Core.Copy all of your code over into a new .NET Core project.
  3. Обращаясь к отчету о переносимости (если он создан), устраните ошибки компилятора, пока проект не будет полностью компилироваться.While referring to the portability report (if generated), solve compiler errors until the project fully compiles.

Хотя такой подход является бессистемным, ориентация на код помогает быстро устранить все проблемы и может оказаться оптимальной для небольших проектов или библиотек.Although this approach is unstructured, the code-focused approach often leads to resolving issues quickly and might be the best approach for smaller projects or libraries. Этот подход лучше применять к проектам, содержащим только модели данных.A project that contains only data models might be an ideal candidate for this approach.

Использование .NET Framework вплоть до устранения проблем переносимостиStaying on the .NET Framework until portability issues are resolved

Такой подход может быть оптимальным, если вам нужен код, который компилируется на протяжении всего процесса.This approach might be the best if you prefer to have code that compiles during the entire process. Он выглядит следующим образом.The approach is as follows:

  1. Запустите средство ApiPort для проекта.Run ApiPort on a project.
  2. Устраните проблемы, используя другие API-интерфейсы, являющиеся переносимыми.Address issues by using different APIs that are portable.
  3. Запомните области, в которых невозможно использовать прямые альтернативы.Take note of any areas where you're prevented from using a direct alternative.
  4. Повторяйте предыдущие шаги для всех переносимых проектов, пока не удостоверитесь в том, что каждый из них готов к копированию в новый проект .NET Core.Repeat the prior steps for all projects you're porting until you're confident each is ready to be copied over into a new .NET Core project.
  5. Скопируйте код в новый проект .NET Core.Copy the code into a new .NET Core project.
  6. Устраните все проблемы, для решения которых нет прямых альтернатив.Work out any issues where you noted that a direct alternative doesn't exist.

Такой тщательный подход более систематизирован, чем простое устранение ошибок компилятора. Но он по-прежнему в некоторой степени ориентирован на код. При этом код является компилируемым на всех этапах.This careful approach is more structured than simply working out compiler errors, but it's still relatively code-focused and has the benefit of always having code that compiles. Есть множество способов устранения некоторых проблем, которые не удалось решить, просто использовав другой API-интерфейс.The way you resolve certain issues that couldn't be addressed by just using another API varies greatly. Для некоторых проектов может оказаться необходимым разработать более детальный план. Эта задача рассматривается в следующем подходе.You may find that you need to develop a more comprehensive plan for certain projects, which is covered as the next approach.

Разработка детального планаDeveloping a comprehensive plan of attack

Это, возможно, наилучший подход для более крупных и сложных проектов, при реализации которых для поддержки .NET Core может потребоваться реструктурировать код или полностью переписать некоторые его части.This approach might be best for larger and more complex projects, where restructuring code or completely rewriting certain areas of code might be necessary to support .NET Core. Он выглядит следующим образом.The approach is as follows:

  1. Запустите средство ApiPort для проекта.Run ApiPort on a project.
  2. Определите, в каких случаях используется каждый непереносимый тип и как он влияет на переносимость в целом.Understand where each non-portable type is used and how that affects overall portability.
    • Изучите особенности этих типов.Understand the nature of those types. Их немного, но они часто используются?Are they small in number but used frequently? Или их много, но используются они нечасто?Are they large in number but used infrequently? Ограничена ли область их использования или они распределены по всему коду?Is their use concentrated, or is it spread throughout your code?
    • Можно ли легко изолировать непереносимый код для более эффективной работы с ним?Is it easy to isolate code that isn't portable so that you can deal with it more effectively?
    • Требуется ли рефакторинг кода?Do you need to refactor your code?
    • Есть ли для непереносимых типов альтернативные интерфейсы API, выполняющие те же задачи?For those types which aren't portable, are there alternative APIs that accomplish the same task? Например, если используется класс WebClient, вместо него можно использовать класс HttpClient.For example if you're using the WebClient class, you might be able to use the HttpClient class instead.
    • Есть ли другие переносимые API-интерфейсы, которые можно использовать для выполнения задачи, даже если это не совсем равноценная замена?Are there different portable APIs available to accomplish a task, even if it's not a drop-in replacement? Например, если вы используете класс XmlSchema для анализа XML, но обнаружение схемы XML вам не требуется, вы можете использовать API-интерфейсыSystem.Xml.Linq и выполнять анализ самостоятельно без API.For example if you're using XmlSchema to parse XML but don't require XML schema discovery, you could use System.Xml.Linq APIs and implement parsing yourself as opposed to relying on an API.
  3. Если у вас есть сборки, которые трудно перенести, возможно, пока стоит оставить их в .NET Framework?If you have assemblies that are difficult to port, is it worth leaving them on .NET Framework for now? Следует учесть ряд факторов:Here are some things to consider:
    • В библиотеке могут быть функции, которые несовместимы с .NET Core, так как они слишком тесно связаны с возможностями .NET Framework или Windows.You may have some functionality in your library that's incompatible with .NET Core because it relies too heavily on .NET Framework or Windows-specific functionality. Возможно, стоит на время отказаться от этих функций и выпустить временную версию библиотеки для .NET Core с ограниченной функциональностью, пока не будет ресурсов для переноса этих функций?Is it worth leaving that functionality behind for now and releasing a .NET Core version of your library with less features on a temporary basis until resources are available to port the features?
    • Поможет ли рефакторинг?Would a refactor help?
  4. Целесообразно ли написание собственной реализации недоступного интерфейса API .NET Framework?Is it reasonable to write your own implementation of an unavailable .NET Framework API? Вы можете рассмотреть возможность копирования, изменения и использования кода из библиотеки эталонного исходного кода .NET Framework.You could consider copying, modifying, and using code from the .NET Framework Reference Source. Эталонный исходный код распространяется по лицензии MIT, поэтому вы можете достаточно свободно использовать его в качестве источника при создании собственного кода.The reference source code is licensed under the MIT License, so you have significant freedom to use the source as a basis for your own code. Только не забывайте соответствующим образом упоминать корпорацию Майкрософт в своем коде.Just be sure to properly attribute Microsoft in your code.
  5. При необходимости повторите этот процесс для различных проектов.Repeat this process as needed for different projects.

Этап анализа может занять некоторое время в зависимости от размера базы кода.The analysis phase could take some time depending on the size of your codebase. Потратив некоторое время на этот этап, чтобы тщательно проанализировать требуемый объем изменений и разработать план, вы сможете сэкономить время в долгосрочной перспективе, особенно если у вас сложная база кода.Spending time in this phase to thoroughly understand the scope of changes needed and to develop a plan usually saves you time in the long run, particularly if you have a complex codebase.

В плане можно предусмотреть внесение существенных изменений в базу кода с сохранением ориентации на .NET Framework 4.7.2, что делает этот подход более структурированным по сравнению с предыдущим.Your plan could involve making significant changes to your codebase while still targeting .NET Framework 4.7.2, making this a more structured version of the previous approach. Способ реализации плана зависит от базы кода.How you go about executing your plan is dependent on your codebase.

Сочетание подходовMixing approaches

В каждом конкретном случае, скорее всего, потребуется использовать описанные выше подходы в разных сочетаниях.It's likely that you'll mix the above approaches on a per-project basis. Выбирайте наиболее подходящие варианты для себя и вашей базы коды.You should do what makes the most sense to you and for your codebase.

Перенос тестовPorting your tests

Чтобы гарантировать правильную работу кода после его переноса в .NET Core, лучше всего тестировать его в процессе переноса.The best way to make sure everything works when you've ported your code is to test your code as you port it to .NET Core. Для этого потребуется использовать платформу тестирования, которая выполняет сборку и запуск тестов для .NET Core.To do this, you'll need to use a testing framework that builds and runs tests for .NET Core. В настоящее время имеются три варианта:Currently, you have three options:

Процедура переноса во многом зависит от того, как структурирован ваш код .NET Framework.Ultimately, the porting effort depends heavily on how your .NET Framework code is structured. Перенос кода лучше всего начинать с основных объектов библиотеки, которые являются базовыми компонентами кода.A good way to port your code is to begin with the base of your library, which are the foundational components of your code. Это могут быть модели данных или какие-либо иные базовые классы и методы, используемые всеми остальными компонентами прямо или косвенно.This might be data models or some other foundational classes and methods that everything else uses directly or indirectly.

  1. Перенесите тестовый проект для тестирования того уровня библиотеки, который вы переносите на данном этапе.Port the test project that tests the layer of your library that you're currently porting.
  2. Скопируйте основные объекты библиотеки в новый проект .NET Core и выберите версию .NET Standard, которая должна поддерживаться.Copy over the base of your library into a new .NET Core project and select the version of the .NET Standard you wish to support.
  3. Внесите изменения, необходимые для компиляции кода.Make any changes needed to get the code to compile. Как правило, для этого требуется добавить зависимости пакетов NuGet в файл CSPROJ.Much of this may require adding NuGet package dependencies to your csproj file.
  4. Проведите тесты и внесите необходимые исправления.Run the tests and make any needed adjustments.
  5. Выберите следующий уровень кода для переноса и повторите предыдущие шаги.Pick the next layer of code to port over and repeat the prior steps.

Двигаясь от базовых объектов библиотеки к более высоким уровням и тестируя каждый из них требуемым образом, вы обеспечиваете систематичность переноса и изоляцию проблем, относящихся к отдельным уровням кода.If you start with the base of your library and move outward from the base and test each layer as needed, porting is a systematic process where problems are isolated to one layer of code at a time.