Jak na .NET Standard knihovny a generování NuGet balíčků


Tvorba NuGet balíčků sice v minulosti nebyla žádná věda, nicméně pokud chtěl vývojář dostat balíček na co největší množství platforem, musel je targetovat pro různé verze a s tím bylo spojeno plno práce v rámci samotného vývoje. Díky .NET Standardu přichází úleva a možnost vytvořit funkční multiplatformní balíček přímou a jednoduchou cestou.

Úvodní slovo k .NET Standardu

V současné době existuje více implementací .NET Frameworku. Mezi nejznámější patří tradiční .NET Framework 4.x, multiplatformní .NET Core 2.x nebo například Mono 5.4. Všechny tyto frameworky v současné době implementují určitou verzi .NET Standardu, čímž se zavazují splňovat všechny její specifikace.

Podle tabulky níže si lze udělat přesnější představu o tom, jaké verze frameworků implementuje která verze .NET Standardu. Z tabulky je vidět, že například .NET Framework 4.6 implementuje .NET Standard 1.3. Je to nejvyšší podporovaná verze a zároveň tedy implementuje i vše, co je v .NET Standard 1.2, 1.1 i 1.0.

Verze .NET Standardu

Jakou verzi .NET Standardu targetovat?

Pokud se jako vývojář rozhodnu, že bych chtěl vyrobit multiplatformní balíček, musím si zvolit vhodnou verzi .NET Standardu. Tato volba je zásadní.

Vyšší verze = více API = menší cílová skupina

Rozhodnu-li se pro nejvyšší verzi .NET Standard 2.0, bude můj balíček moci používat více API, než u starších verzí. Zároveň je třeba si uvědomit, že takovou sadu API splňují jen novější verze cílových frameworků (např.: .NET Framework 4.6.1 a .NET Core 2.0). Znamená to, že vývojář, který píše webovou aplikaci targetující .NET Core 1.0 už takový balíček nebude moci použít.

Nižší verze = méně API = větší cílová skupina

Ideální je tedy zvolit co nejnižší verzi .NET Standardu, která je pro mé účely vybavena vším, co můj balíček bude potřebovat. Nižší verzi .NET Standardu splňují již nižší verze frameworků, čímž takový balíček bude moci použít mnohem více vývojářů.

Chcete-li tedy vytvořit jednoduchý balíček, který nepoužívá žádné extra funkce, pak nemá smysl targetovat nejnovější verze .NET Standardu.

Praktická ukázka knihovny

Praktickým příkladem zjednodušení může být knihovna (NuGet balíček) FioSDK, který jsem v minulosti udržoval a bojoval s targetováním pro různé verze frameworků. Obskurní přístupy jsou dnes díky .NET Standardu minulostí:

Targetování v době, když tu nebyl .NET Standard

Takto transformovaný NuGet balíček targetuje .NET Standard 1.3 a může být tudíž použit pro vývoj aplikací nad .NET Core od verze 1.0, .NET Frameworku 4.6 ale i pro vývoj s Mono, Xamarinem nebo pro univerzální aplikace (UWP).

Vytváření NuGet balíčků

Pokud se rozhodnu udělat C# knihovnu, ze které budu dělat NuGet balíček, pak v první řadě musím knihovnu natargetovat na vybranou verzi .NET Standardu na úrovni projektu:

Target Framework v Rider

Výsledkem klikání v libovolném GUI je úprava v projektovém souboru:

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

Hotovo. Zkompilovatelný projekt už nyní mohu vypublikovat do podoby NuGet balíčku.

Vytvoření NuGet balíčku s dotnet CLI

Existuje více možností jak vytvořit NuGet balíček. V článku popíši velmi elegantní řešení pomocí nástroje dotnet CLI. Pro použití nástroje je potřeba nainstalovat .NET Core SDK, jehož součástí je právě i dotnet CLI. Po instalaci SDK je možné ověřit funkčnost zavoláním příkazu dotnet v CMD nebo terminálu.

Ukázka nástroje dotnet v terminálu

Jestliže mám k dispozici dotnet, stačí se nascopovat na úroveň projektu a zavolat nejprve příkaz dotnet build pro sestavení projektu a následně příkaz dotnet pack pro vytvoření NuGet balíčku. Ten je zároveň i velmi snadno konfigurovatelný:

Možnosti dotnet pack

Nastavení informací o NuGet balíčku

Protože budeme chtít připojit k NuGet balíčku i užitečné informace, jako například název, verzi, popis, ikonu atd., musíme připravit specifikaci. "Po staru" bychom mohli jít cestou nuspec souboru, nicméně snazší je informace rovnou zahrnout do projektového souboru. Všechny údaje k NuGet balíčku jsou označovány jako metadata a jejich kompletní přehled je dostupný online v MSDN dokumentaci.

Kompletní projektový soubor (csproj) pak může vypadat například takto:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netstandard1.3</TargetFramework>
        <PackageId>FioSdk</PackageId>
        <Version>2.0.0</Version>
        <Description>FIO Banka SDK for C#</Description>
        <Copyright>© 2016 - 2018</Copyright>
        <Language>en-US</Language>
        <Authors>Miroslav Holec</Authors>
        <Title>FIO Banka SDK for C#</Title>
        <PackageIconUrl>https://holecdrive.blob.core.windows.net/nuget/fio-sdk.png</PackageIconUrl>
        <PackageProjectUrl>https://github.com/mholec/fio-sdk-csharp</PackageProjectUrl>
        <PackageLicenseUrl>https://github.com/mholec/fio-sdk-csharp/blob/master/LICENSE</PackageLicenseUrl>
        <PackageTags>fio, sdk, api, banka</PackageTags>
        <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Newtonsoft.Json" Version="9.0.1"/>
    </ItemGroup>
</Project>

Již na první pohled je zřejmá jedna výhoda, kterou jsou závislosti na jiných NuGet balíčkách (nemusíme tyto závislosti uvádět dvojmo v nuspec). Zároveň bych upozornil na element GeneratePackageOnBuild, který mi zajišťuje, že výstupem každého buildu bude zároveň i nový NuGet balíček. Po sestavení projektu na build serveru tak mohu vykopírovat nupkg soubory do artefaktů a připravit je na release.

Vytvořený NuGet balíček (soubor nupkg) najdeme ve složce bin, kde je i samotná složka s jeho obsahem (včetně dll).

Vytvořený nupkg balíček

Část záznamu z přednášky, kde o .NET Standardu mluvím

Závěrečné poznámky

Popsaný způsob tvorby NuGet balíčků není rozhodně jediný, jen si myslím, že může být pro mnoho vývojářů nejsnazší cestou, jak s balíčkováním začít. V některém z dalších článků popíšu, jak si nastavit CI buildy a Continuous Deployment.

 

Miroslav Holec

Comments (0)

Skip to main content