web-dev-qa-db-ja.com

メタパッケージに依存するnetstandardライブラリのアプリケーションの意味は何ですか?

Netstandard1.3をターゲットにしたいが、BigIntegerも使用するクラスライブラリがあるとします。簡単な例を次に示します-唯一のソースファイルはAdder.csです:

using System;
using System.Numerics;

namespace Calculator
{
    public class Adder
    {
        public static BigInteger Add(int x, int y)
            => new BigInteger(x) + new BigInteger(y);            
    }
}

project.jsonの世界に戻り、frameworksセクションのnetstandard1.3をターゲットにし、System.Runtime.Numericsに明示的に依存します。バージョン4.0.1私が作成するnugetパッケージは、その依存関係のみをリストします。

Csprojベースのドットネットツールの勇敢な新しい世界(私はコマンドラインツールのv1.0.1を使用しています)では、ターゲット設定時にNETStandard.Library 1.6.1への 暗黙のメタパッケージパッケージ参照 がありますnetstandard1.3。これは、明示的な依存関係を必要としないため、プロジェクトファイルが非常に小さいことを意味します。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
  </PropertyGroup>
</Project>

...しかし、生成されたnugetパッケージはNETStandard.Libraryに依存しているため、私の小さなライブラリを使用するには、everythingが必要です。そこ。

DisableImplicitFrameworkReferencesを使用してその機能を無効にし、手動で依存関係を再度追加できることがわかりました。

<Project Sdk="Microsoft.NET.Sdk">    
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
    <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Runtime.Numerics" Version="4.0.1" />
  </ItemGroup>    
</Project>

今、私のNuGetパッケージは、依存する内容を正確に示しています。直感的には、これは「学習者」パッケージのように感じられます。

それで、私のライブラリの消費者にとって正確な違いは何ですか?誰かがUWPアプリケーションでそれを使用しようとすると、依存関係の2番目の「トリミングされた」形式は、結果のアプリケーションが小さくなることを意味しますか?

DisableImplicitFrameworkReferencesを明確に文書化しないこと(私が見た限り、私はそれについて を問題 で読みました)およびプロジェクト作成時に暗黙的な依存関係をデフォルトにすることにより、マイクロソフトはメタパッケージに依存するようにユーザーを奨励していますが、クラスライブラリパッケージを作成しているときに不利な点がないことをどのように確認できますか?

97
Jon Skeet

これまで、開発者は、NuGetパッケージのメタパッケージ(NETStandard.Library)を参照せず、代わりにSystem.RuntimeSystem.Collectionsなどの個別のパッケージを参照することを推奨しています。理論的な理由は、メタパッケージを、.NETプラットフォームの実際のアトミックビルディングブロックである一連のパッケージの省略形だと考えたからです。仮定は、これらのアトミックブロックの一部のみをサポートし、それらのすべてをサポートしない別の.NETプラットフォームを作成する可能性があることです。したがって、参照するパッケージが少ないほど、よりポータブルになります。また、私たちのツールが大きなパッケージグラフをどのように扱うかについての懸念もありました。

今後、これを単純化します。

  1. 。NET Standardはアトミックビルディングブロックです。言い換えれば、新しいプラットフォームは.NET Standardのサブセット化を許可されていません。すべてを実装する必要があります。

  2. 。NET標準を含む、プラットフォームを記述するためにパッケージを使用することから離れています。

つまり、.NET StandardのNuGetパッケージを参照する必要がなくなります。 libフォルダーで依存関係を表明しました。これは、他のすべての.NETプラットフォーム、特に.NET Frameworkで正確に機能する方法です。

ただし、今のところ、ツールはNETStandard.Libraryへの参照を引き続き書き込みます。害はありませんが、前進するだけで冗長になります。

.NET Standardリポジトリの [〜#〜] faq [〜#〜] を更新して、この質問を含めます。

更新:この質問は現在 FAQの一部 です。

75
Immo Landwerth

チームは、最もスリムなパッケージセットが何であるかを理解することを推奨していました。彼らはもはやこれを行わず、代わりにNETStandard.Libraryを持ち込むことを推奨します(SDKスタイルのプロジェクトの場合、これは自動的に行われます)。

なぜそうなのかについて、まったくまっすぐな答えを得たことがないので、経験に基づいた推測をさせてください。

主な理由は、ターゲットフレームワークを変更するときに自分で追跡する必要がある依存ライブラリのバージョンの違いを隠すことができるためです。また、SDKベースのプロジェクトファイルを使用したユーザーフレンドリーなシステムです。プラットフォームのまともなチャンクを取得するために、参照をまったく必要としないためです(デスクトップランドのデフォルトの参照、特にmscorlibで使用するのと同じように) )。

netstandardライブラリまたはnetcoreappアプリケーションであることの意味のメタ定義を適切なNuGetパッケージにプッシュすることにより、特別な知識を組み込みの定義に組み込む必要がありません。 Visual Studio(またはdotnet new)それらを見ます。

公開時に静的分析を使用して、出荷されたDLLを制限することができます。これは、UWPのネイティブコンパイルを行う際に現在行われていることです(ただし注意が必要です)。彼らは今日、.NET Coreに対してそれをしていませんが、私はそれが彼らが考慮した最適化であると推測します(そしてネイティブコードをサポートします)。

あなたがそう選択した場合、あなたが非常に選択的であることを妨げるものは何もありません。あなたがそれをしているのはあなただけであることに気付くと思いますが、それは目的をも破ります(誰もがNETStandard.Library または Microsoft.NETCore.App)。

18
Brad Wilson

暗黙の参照を無効にする必要はありません。ライブラリが実行できるすべてのプラットフォームには、NETStandard.Library依存関係が必要とするアセンブリが既にあります。

.NET標準ライブラリは、.NET Coreや.NET Frameworkなど、プラットフォームの既知のセットとバージョンに存在することが保証されているAPIのセットを提供する、コンパイル対象のリファレンスアセンブリの仕様です。 。これらのアセンブリの実装ではなく、コンパイラがコードを正常にビルドできるようにするのに十分なAPIシェイプです。

これらのAPIの実装は、.NET Core、Mono、.NET Frameworkなどのターゲットプラットフォームによって提供されます。プラットフォームの重要な部分であるため、プラットフォームに同梱されています。したがって、より小さい依存関係セットを指定する必要はありません。すべてがすでに存在しているので、変更することはありません。

NETStandard.Libraryパッケージは、これらの参照アセンブリを提供します。混乱の1つのポイントはバージョン番号です。パッケージはバージョン1.6.1ですが、これは「.NET Standard 1.6」を意味するものではありません。パッケージのバージョンです。

ターゲットとする.NET Standardのバージョンは、プロジェクトで指定するターゲットフレームワークから取得されます。

ライブラリを作成していて、それを.NET Standard 1.3で実行する場合は、NETStandard.Libraryパッケージ(現在バージョン1.6.1)を参照します。しかし、もっと重要なのは、プロジェクトファイルがnetstandard1.3を対象とすることです。

NETStandard.Libraryパッケージは、ターゲットフレームワークモニカーに応じて異なる参照アセンブリのセットを提供します(簡潔にするために単純化していますが、lib\netstandard1.0lib\netstandard1.1、および 依存グループ )。したがって、プロジェクトがnetstandard1.3をターゲットにしている場合、1.3参照アセンブリを取得できます。 netstandard1.6をターゲットにすると、1.6リファレンスアセンブリが取得されます。

アプリケーションを作成している場合、.NET Standardをターゲットにすることはできません。意味がありません-仕様で実行することはできません。代わりに、net452netcoreapp1.1などの具体的なプラットフォームをターゲットにします。 NuGetは、これらのプラットフォームとnetstandardターゲットフレームワークモニカー間のマッピングを認識しているため、どのlib\netstandardX.Xフォルダーがターゲットプラットフォームと互換性があるかを認識します。また、NETStandard.Libraryの依存関係がターゲットプラットフォームによって満たされていることもわかっているため、他のアセンブリを取り込むことはありません。

同様に、スタンドアロンの.NET Coreアプリを作成すると、.NET Standard実装アセンブリがアプリとともにコピーされます。 NETStandard.Libraryへの参照は、他の新しいアプリをもたらしません。

dotnet publishはスタンドアロンアプリケーションを作成します ですが、現在はトリミングを行わず、すべてのアセンブリを公開します。これは ツールによって自動的に処理されます になります。そのため、ここでもライブラリの依存関係をトリミングしても役に立ちません。

私が想像できる唯一の場所は、mightNETStandard.Library参照を削除するのに役立ちます。NET標準をサポートしないプラットフォームをターゲットにしている場合、そしてすべての推移的な依存関係がターゲットプラットフォームで実行できる.NET標準からパッケージを見つけることができます。私はその法案に合うパッケージは多くないと思います。

8
citizenmatt