.NET ライブラリに依存関係を追加する主な方法は、NuGet パッケージを参照することです。 NuGet パッケージ参照を使用すると、既に記述されている機能をすばやく再利用して活用できますが、これは .NET 開発者にとって一般的な摩擦の原因です。 依存関係を正しく管理することは、他の .NET ライブラリの変更によって .NET ライブラリが破損するのを防ぐために重要です。その逆も同様です。
ダイヤモンド依存関係
.NET プロジェクトの依存関係ツリーには、パッケージの複数のバージョンが含まれるのが一般的です。 たとえば、アプリは 2 つの NuGet パッケージに依存し、それぞれが同じパッケージの異なるバージョンに依存します。 ダイヤモンド型の依存関係がアプリの依存関係グラフに存在しています。
ビルド時に、NuGet は依存関係の依存関係を含め、プロジェクトが依存するすべてのパッケージを分析します。 パッケージの複数のバージョンが検出されると、1 つを選択するルールが評価されます。 .NET では、同じアプリケーションでアセンブリのサイド バイ サイド バージョンを実行することが問題になるため、パッケージを統合する必要があります。
ほとんどのダイヤモンドの依存関係は簡単に解決できます。ただし、特定の状況で問題が発生する可能性があります。
- NuGet パッケージ参照が競合 すると、パッケージの復元中にバージョンが解決されなくなります。
- バージョン間の破壊的変更により、実行時に バグと例外が発生します。
- パッケージ アセンブリは厳密な名前が付けられ、アセンブリのバージョンが変更され、アプリは .NET Framework で実行されています。 アセンブリ バインドリダイレクトが必要です。
どのようなパッケージが自分のパッケージと共に使用されるかを知ることはできません。 ダイヤモンドの依存関係がライブラリを壊す可能性を減らす良い方法は、依存するパッケージの数を最小限に抑える方法です。
✔️ 不要な依存関係については、.NET ライブラリを確認してください。
NuGet 依存関係バージョンの範囲
パッケージ参照は、有効なパッケージの範囲を指定します。 通常、プロジェクト ファイル内のパッケージ参照バージョンは最小バージョンであり、最大値はありません。
<!-- Accepts any version 1.0 and above. -->
<PackageReference Include="ExamplePackage" Version="1.0" />
依存関係を解決するときに NuGet が使用する規則は 複雑ですが、 既定では NuGet は適用可能な最も低いバージョンを探します。 NuGet では、互換性の問題が最も少ないため、使用可能な最大値を使用するよりも、適用可能なバージョンが最も低い方が優先されます。
NuGet の適用可能なバージョン規則が最も低いため、最新バージョンを取得しないように、パッケージ参照に上位バージョンまたは正確な範囲を配置する必要はありません。 NuGet は、互換性が最も低いバージョンを既に見つけようとします。
<!-- Accepts 1.0 up to 1.x, but not 2.0 and higher. -->
<PackageReference Include="ExamplePackage" Version="[1.0,2.0)" />
<!-- Accepts exactly 1.0. -->
<PackageReference Include="ExamplePackage" Version="[1.0]" />
バージョン制限を超えていると、競合が発生した場合に NuGet が失敗します。 たとえば、1 つのライブラリでは 1.0 を受け入れますが、別のライブラリでは 2.0 以上が必要です。 バージョン 2.0 では破壊的変更が導入された可能性があります。厳密または上限バージョンの依存関係によってエラーが保証されます。
❌ 最小バージョンのない NuGet パッケージ参照を持たないでください。
❌ 正確なバージョンを要求する NuGet パッケージ参照を回避します。
❌ バージョンの上限を持つ NUGet パッケージ参照を回避します。
詳細については、「 パッケージのバージョン管理」を参照してください。
NuGet 共有ソース パッケージ
外部 NuGet パッケージの依存関係を減らす 1 つの方法は、共有ソース パッケージを参照することです。 共有ソース パッケージには、参照時にプロジェクトに含まれる ソース コード ファイル が含まれています。 プロジェクトの残りの部分でコンパイルされたソース コード ファイルのみを含んでいるため、外部の依存関係や競合の可能性はありません。
共有ソース パッケージは、小さな機能を含めるのに最適です。 たとえば、HTTP 呼び出しを行うためのヘルパー メソッドの共有ソース パッケージを参照できます。
<PackageReference Include="Microsoft.Extensions.Buffers.Testing.Sources" PrivateAssets="All" Version="1.0" />
共有ソース パッケージには、いくつかの制限があります。
PackageReferenceによってのみ参照できるため、古いpackages.config プロジェクトは除外されます。 また、共有ソース パッケージは、同じ言語のプロジェクトでのみ使用できます。 これらの制限により、共有ソース パッケージは、オープンソース プロジェクト内で機能を共有するために最適です。
✔️ 小規模な内部機能については、共有ソース パッケージを参照することを検討してください。
✔️ 小さな内部機能が提供される場合は、パッケージを共有ソース パッケージにすることを検討してください。
✔️ PrivateAssets="All"で共有ソース パッケージを参照してください。
この設定は、パッケージが開発時にのみ使用され、パブリック依存関係として公開されないように NuGet に指示します。
❌ パブリック API に共有ソース パッケージの種類を含めないでください。
共有ソース型は参照元アセンブリにコンパイルされ、アセンブリの境界を越えて交換することはできません。 たとえば、あるプロジェクトの共有ソース
IRepository型は、別のプロジェクトの同じ共有ソースIRepositoryとは別の種類です。 共有ソース パッケージ内の型は、internal可視性を持つ必要があります。
❌ 共有ソース パッケージを NuGet.org に発行しないでください。
共有ソース パッケージにはソース コードが含まれており、同じ言語の種類のプロジェクトでのみ使用できます。 たとえば、C# 共有ソース パッケージを F# アプリケーションで使用することはできません。
共有ソース パッケージを ローカル フィードまたは MyGet に発行して、プロジェクト内で内部的に使用します。
.NET