Vývoj knihoven pomocí .NET CLI

Tento článek popisuje, jak psát knihovny pro .NET pomocí rozhraní příkazového řádku .NET. Rozhraní příkazového řádku poskytuje efektivní a nízké prostředí, které funguje v jakémkoli podporovaném operačním systému. Knihovny můžete vytvářet i v sadě Visual Studio a pokud je to vaše preferované prostředí , projděte si průvodce sadou Visual Studio.

Požadavky

Na svém počítači potřebujete nainstalovanou sadu .NET SDK .

V částech tohoto dokumentu, které se zabývají verzemi rozhraní .NET Framework, potřebujete rozhraní .NET Framework nainstalované na počítači s Windows.

Kromě toho, pokud chcete podporovat starší cíle rozhraní .NET Framework, musíte nainstalovat cílové balíčky nebo sady developer pack ze stránky pro stahování rozhraní .NET Framework. Projděte si tuto tabulku:

Verze rozhraní .NET Framework Co stáhnout
4.6.1 Sada cílení rozhraní .NET Framework 4.6.1
4.6 Balíček cílení rozhraní .NET Framework 4.6
4.5.2 Sada .NET Framework 4.5.2 Developer Pack
4.5.1 .NET Framework 4.5.1 Developer Pack
4.5 Sada Windows SDK pro aplikace pro Windows 8
4.0 Windows SDK pro Windows 7 a .NET Framework 4
2.0, 3.0 a 3.5 .NET Framework 3.5 SP1 Runtime (nebo verze Windows 8 nebo novější)

Jak cílit na .NET 5 nebo .NET Standard

Cílovou architekturu projektu můžete řídit jeho přidáním do souboru projektu (.csproj nebo .fsproj). Pokyny k výběru mezi cílením na .NET 5 nebo .NET Standard najdete v tématech .NET 5+ a .NET Standard.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
</Project>

Pokud chcete cílit na rozhraní .NET Framework verze 4.0 nebo nižší, nebo chcete použít rozhraní API dostupné v rozhraní .NET Framework, ale ne v rozhraní .NET Standard (například), přečtěte si následující části a zjistěte, System.Drawingjak provést více cílů.

Jak cílit na rozhraní .NET Framework

Poznámka:

Tyto pokyny předpokládají, že máte na počítači nainstalované rozhraní .NET Framework. Informace o instalaci závislostí najdete v části Požadavky .

Mějte na paměti, že některé zde použité verze rozhraní .NET Framework už nejsou podporované. Nejčastější dotazy k nepodporovaným verzím najdete v zásadách životního cyklu podpory rozhraní .NET Framework.

Pokud chcete dosáhnout maximálního počtu vývojářů a projektů, použijte jako cíl směrného plánu rozhraní .NET Framework 4.0. Pokud chcete cílit na rozhraní .NET Framework, začněte správným monikerem cílového rozhraní (TFM), který odpovídá verzi rozhraní .NET Framework, kterou chcete podporovat.

Verze rozhraní .NET Framework TFM
.NET Framework 2,0 net20
.NET Framework 3.0 net30
.NET Framework 3.5 net35
.NET Framework 4.0 net40
.NET Framework 4.5 net45
.NET Framework 4.5.1 net451
.NET Framework 4.5.2 net452
.NET Framework 4.6 net46
.NET Framework 4.6.1 net461
.NET Framework 4.6.2 net462
.NET Framework 4.7 net47
.NET Framework 4.8 net48

Tento TFM pak vložíte do TargetFramework části souboru projektu. Tady je příklad, jak byste napsali knihovnu, která cílí na rozhraní .NET Framework 4.0:

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

A to je vše! I když je tento kompilovaný pouze pro rozhraní .NET Framework 4, můžete knihovnu použít v novějších verzích rozhraní .NET Framework.

Postup cílení na více verzí

Poznámka:

Následující pokyny předpokládají, že máte na počítači nainstalovanou rozhraní .NET Framework. V části Požadavky se dozvíte, ze kterých závislostí je potřeba nainstalovat a odkud je stáhnout.

Možná budete muset cílit na starší verze rozhraní .NET Framework, pokud váš projekt podporuje rozhraní .NET Framework i .NET. Pokud v tomto scénáři chcete pro novější cíle použít novější rozhraní API a jazykové konstrukty, použijte #if ve svém kódu direktivy. Možná budete také muset přidat různé balíčky a závislosti pro každou platformu, na kterou cílíte, aby zahrnovala různá rozhraní API potřebná pro každý případ.

Řekněme například, že máte knihovnu, která provádí síťové operace přes protokol HTTP. Pro .NET Standard a rozhraní .NET Framework verze 4.5 nebo vyšší můžete použít HttpClient třídu z System.Net.Http oboru názvů. Starší verze rozhraní .NET Framework však nemají HttpClient třídu, takže byste mohli místo toho použít WebClient třídu z System.Net oboru názvů.

Soubor projektu může vypadat takto:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;net40;net45</TargetFrameworks>
  </PropertyGroup>

  <!-- Need to conditionally bring in references for the .NET Framework 4.0 target -->
  <ItemGroup Condition="'$(TargetFramework)' == 'net40'">
    <Reference Include="System.Net" />
  </ItemGroup>

  <!-- Need to conditionally bring in references for the .NET Framework 4.5 target -->
  <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Threading.Tasks" />
  </ItemGroup>
</Project>

Tady si všimnete tří hlavních změn:

  1. Uzel TargetFramework se nahradil TargetFrameworksa uvnitř jsou vyjádřeny tři TFM.
  2. Pro načtení cíle v jednom odkazu rozhraní .NET Framework existuje <ItemGroup> uzel net40 .
  3. Cílový pulling má <ItemGroup> uzel net45 ve dvou odkazech rozhraní .NET Framework.

Symboly preprocesoru

Systém sestavení si uvědomuje následující symboly preprocesoru používané ve #if direktivách:

Cílové architektury Symboly Další symboly
(k dispozici v sadách .NET 5+ SDK)
Symboly platformy (k dispozici pouze
při zadání TFM specifického pro operační systém)
.NET Framework NETFRAMEWORK, NET48, , NET472, NET47NET462, NET40NET35NET471NET461NET46NET452NET451NET45NET20 NET48_OR_GREATER, NET472_OR_GREATER, , NET471_OR_GREATER, NET462_OR_GREATERNET47_OR_GREATER, NET461_OR_GREATERNET40_OR_GREATERNET452_OR_GREATERNET46_OR_GREATERNET451_OR_GREATERNET45_OR_GREATER, NET35_OR_GREATERNET20_OR_GREATER
.NET Standard NETSTANDARD, NETSTANDARD2_1, , NETSTANDARD2_0, NETSTANDARD1_5NETSTANDARD1_6, NETSTANDARD1_4NETSTANDARD1_3NETSTANDARD1_2, , NETSTANDARD1_1NETSTANDARD1_0 NETSTANDARD2_1_OR_GREATER, NETSTANDARD2_0_OR_GREATER, , NETSTANDARD1_5_OR_GREATERNETSTANDARD1_3_OR_GREATERNETSTANDARD1_2_OR_GREATERNETSTANDARD1_6_OR_GREATERNETSTANDARD1_4_OR_GREATER, , NETSTANDARD1_1_OR_GREATERNETSTANDARD1_0_OR_GREATER
.NET 5+ (a .NET Core) NET, NET8_0, , NET7_0, NET5_0NET6_0, NETCOREAPPNETCOREAPP2_0NETCOREAPP3_0NETCOREAPP3_1NETCOREAPP2_2NETCOREAPP2_1, NETCOREAPP1_1NETCOREAPP1_0 NET8_0_OR_GREATER, NET7_0_OR_GREATER, , NET6_0_OR_GREATER, NETCOREAPP3_1_OR_GREATERNETCOREAPP2_0_OR_GREATERNET5_0_OR_GREATERNETCOREAPP3_0_OR_GREATERNETCOREAPP2_2_OR_GREATERNETCOREAPP2_1_OR_GREATER, NETCOREAPP1_1_OR_GREATERNETCOREAPP1_0_OR_GREATER ANDROID, BROWSER, IOS, , MACOSMACCATALYST, TVOS, , WINDOWS
[OS][version] (například IOS15_1),
[OS][version]_OR_GREATER (například IOS15_1_OR_GREATER)

Poznámka:

  • Symboly bez verzí se definují bez ohledu na verzi, na kterou cílíte.
  • Symboly specifické pro verzi jsou definované jenom pro verzi, na kterou cílíte.
  • Symboly <framework>_OR_GREATER jsou definované pro verzi, na kterou cílíte, a všechny předchozí verze. Pokud například cílíte na rozhraní .NET Framework 2.0, jsou definovány následující symboly: NET20, NET20_OR_GREATER, NET11_OR_GREATERa NET10_OR_GREATER.
  • Symboly NETSTANDARD<x>_<y>_OR_GREATER jsou definovány pouze pro cíle .NET Standard, a ne pro cíle, které implementují .NET Standard, jako jsou .NET Core a .NET Framework.
  • Liší se od monikers cílové architektury (TFMs) používané vlastností MSBuild TargetFramework a NuGet.

Tady je příklad použití podmíněné kompilace podle cíle:

using System;
using System.Text.RegularExpressions;
#if NET40
// This only compiles for the .NET Framework 4 targets
using System.Net;
#else
 // This compiles for all other targets
using System.Net.Http;
using System.Threading.Tasks;
#endif

namespace MultitargetLib
{
    public class Library
    {
#if NET40
        private readonly WebClient _client = new WebClient();
        private readonly object _locker = new object();
#else
        private readonly HttpClient _client = new HttpClient();
#endif

#if NET40
        // .NET Framework 4.0 does not have async/await
        public string GetDotNetCount()
        {
            string url = "https://www.dotnetfoundation.org/";

            var uri = new Uri(url);

            string result = "";

            // Lock here to provide thread-safety.
            lock(_locker)
            {
                result = _client.DownloadString(uri);
            }

            int dotNetCount = Regex.Matches(result, ".NET").Count;

            return $"Dotnet Foundation mentions .NET {dotNetCount} times!";
        }
#else
        // .NET Framework 4.5+ can use async/await!
        public async Task<string> GetDotNetCountAsync()
        {
            string url = "https://www.dotnetfoundation.org/";

            // HttpClient is thread-safe, so no need to explicitly lock here
            var result = await _client.GetStringAsync(url);

            int dotNetCount = Regex.Matches(result, ".NET").Count;

            return $"dotnetfoundation.org mentions .NET {dotNetCount} times in its HTML!";
        }
#endif
    }
}

Pokud tento projekt sestavíte pomocí dotnet build, všimnete si tří adresářů ve bin/ složce:

net40/
net45/
netstandard2.0/

Každý z těchto souborů obsahuje .dll soubory pro každý cíl.

Testování knihoven v .NET

Je důležité, abyste mohli testovat na různých platformách. Můžete použít buď xUnit , nebo MSTest out of the box. Oba jsou dokonale vhodné pro testování jednotek vaší knihovny v .NET. Způsob nastavení řešení s testovacími projekty bude záviset na struktuře vašeho řešení. Následující příklad předpokládá, že testovací a zdrojové adresáře žijí ve stejném adresáři nejvyšší úrovně.

Poznámka:

K tomu se používají některé příkazy rozhraní příkazového řádku .NET. Další informace najdete v tématu dotnet new a dotnet sln .

  1. Nastavte řešení. Můžete to udělat pomocí následujících příkazů:

    mkdir SolutionWithSrcAndTest
    cd SolutionWithSrcAndTest
    dotnet new sln
    dotnet new classlib -o MyProject
    dotnet new xunit -o MyProject.Test
    dotnet sln add MyProject/MyProject.csproj
    dotnet sln add MyProject.Test/MyProject.Test.csproj
    

    Tím vytvoříte projekty a propojíte je v řešení. SolutionWithSrcAndTest Adresář by měl vypadat takto:

    /SolutionWithSrcAndTest
    |__SolutionWithSrcAndTest.sln
    |__MyProject/
    |__MyProject.Test/
    
  2. Přejděte do adresáře testovacího projektu a přidejte odkaz na MyProject.Test z MyProject.

    cd MyProject.Test
    dotnet add reference ../MyProject/MyProject.csproj
    
  3. Obnovení balíčků a projektů sestavení:

    dotnet restore
    dotnet build
    
  4. Spuštěním dotnet test příkazu ověřte, že xUnit běží. Pokud jste se rozhodli použít MSTest, měl by se spustit spouštěč konzoly MSTest.

A to je vše! Knihovnu teď můžete otestovat na všech platformách pomocí nástrojů příkazového řádku. Pokud chcete pokračovat v testování, když máte všechno nastavené, testování knihovny je velmi jednoduché:

  1. Proveďte změny v knihovně.
  2. Pomocí příkazu spusťte testy z příkazového řádku v testovacím dotnet test adresáři.

Kód se při vyvolání příkazu automaticky znovu sestaví dotnet test .

Jak používat více projektů

Běžnou potřebou větších knihoven je umístit funkce do různých projektů.

Představte si, že chcete vytvořit knihovnu, která by mohla být využita v idiomaticích C# a F#. To by znamenalo, že uživatelé vaší knihovny ji využívají způsoby, které jsou přirozené pro C# nebo F#. Například v jazyce C# můžete knihovnu využívat takto:

using AwesomeLibrary.CSharp;

public Task DoThings(Data data)
{
    var convertResult = await AwesomeLibrary.ConvertAsync(data);
    var result = AwesomeLibrary.Process(convertResult);
    // do something with result
}

V jazyce F# to může vypadat takto:

open AwesomeLibrary.FSharp

let doWork data = async {
    let! result = AwesomeLibrary.AsyncConvert data // Uses an F# async function rather than C# async method
    // do something with result
}

Scénáře spotřeby, jako je tento, znamenají, že přístupná rozhraní API musí mít jinou strukturu pro C# a F#. Běžným přístupem k tomuto účelu je zohlednit veškerou logiku knihovny do základního projektu pomocí projektů C# a F# definujících vrstvy rozhraní API, které do tohoto základního projektu volají. Zbývající část oddílu bude používat následující názvy:

  • AwesomeLibrary.Core – základní projekt, který obsahuje veškerou logiku pro knihovnu
  • AwesomeLibrary.CSharp – projekt s veřejnými rozhraními API určenými ke spotřebě v jazyce C#
  • AwesomeLibrary.FSharp – projekt s veřejnými rozhraními API určenými ke spotřebě v F#

V terminálu můžete spustit následující příkazy, které vytvoří stejnou strukturu jako v tomto průvodci:

mkdir AwesomeLibrary && cd AwesomeLibrary
dotnet new sln
mkdir AwesomeLibrary.Core && cd AwesomeLibrary.Core && dotnet new classlib
cd ..
mkdir AwesomeLibrary.CSharp && cd AwesomeLibrary.CSharp && dotnet new classlib
cd ..
mkdir AwesomeLibrary.FSharp && cd AwesomeLibrary.FSharp && dotnet new classlib -lang "F#"
cd ..
dotnet sln add AwesomeLibrary.Core/AwesomeLibrary.Core.csproj
dotnet sln add AwesomeLibrary.CSharp/AwesomeLibrary.CSharp.csproj
dotnet sln add AwesomeLibrary.FSharp/AwesomeLibrary.FSharp.fsproj

Tím se přidají výše uvedené tři projekty a soubor řešení, který je propojí dohromady. Vytvoření souboru řešení a propojení projektů vám umožní obnovit a sestavit projekty z nejvyšší úrovně.

Odkazování na projekt

Nejlepším způsobem, jak odkazovat na projekt, je přidat odkaz na projekt pomocí rozhraní příkazového řádku .NET. Z adresářů projektů AwesomeLibrary.CSharp a AwesomeLibrary.FSharp můžete spustit následující příkaz:

dotnet add reference ../AwesomeLibrary.Core/AwesomeLibrary.Core.csproj

Soubory projektu pro AwesomeLibrary.CSharp i AwesomeLibrary.FSharp teď budou odkazovat na ProjectReference AwesomeLibrary.Core jako cíl. Můžete to ověřit kontrolou souborů projektu a zobrazením následujících možností:

<ItemGroup>
  <ProjectReference Include="..\AwesomeLibrary.Core\AwesomeLibrary.Core.csproj" />
</ItemGroup>

Pokud nechcete používat .NET CLI, můžete tento oddíl přidat do každého souboru projektu ručně.

Strukturování řešení

Dalším důležitým aspektem řešení s více projekty je vytvoření dobré celkové struktury projektu. Kód můžete uspořádat tak, jak se vám líbí, a pokud každý projekt propojíte se souborem řešení , dotnet sln addbudete moct spouštět dotnet restore a dotnet build na úrovni řešení.