.NET Framework ライブラリを .NET Core に移植するPort .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\ このトピックでは、すべての .NET 実装で使用可能にすることを目的とした、.NET API の正式な仕様について説明します。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
このトピックでは、クロスプラットフォーム CLI ツールを使用して .NET 用ライブラリを作成する方法について説明します。This topic explains how to write libraries for .NET using cross-platform CLI tools.

.NET Core の csproj 形式に追加されたもの 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.2 に変更するRetargeting your .NET Framework code to .NET Framework 4.7.2

コードのターゲットが .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. ターゲット設定することで、.NET Standard が既存の API をサポートしていない場合に、最新の代替 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. [対象とする 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 Portability Analyzer (ApiPort) を実行して、分析用の移植性レポートを生成します。The next step is to run the API Portability Analyzer (ApiPort) to generate a portability report for analysis.

API Portability Analyzer (ApiPort) を理解し、.NET Core をターゲットとする移植性レポートを生成する方法を理解している必要があります。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

このアプローチは、小さなプロジェクト、つまり多くの .NET Framework API を使用しないプロジェクトにお勧めです。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 スキーマ検出が不要な場合、System.Xml.Linq API を使用して 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 Framework または Windows 固有の機能への依存度が高いために、.NET Core との互換性がない機能がライブラリにあるとします。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. 使用できない .NET Framework API の代わりになる実装を開発することは理にかなっていますか。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. ただし、コードには Microsoft への帰属を適切に示してください。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. 現在のところ、次の 3 つの選択肢があります。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.

ライブラリのベースから開始してベースから外側に向かい、必要に応じて各レイヤーをテストする場合、移植は、問題が一度でコードの 1 レイヤーに分離される体系的なプロセスになります。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.