Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Den här artikeln beskriver hur du skriver bibliotek för .NET med hjälp av .NET CLI. CLI ger en effektiv och grundläggande upplevelse som fungerar över alla operativsystem som stöds. Du kan fortfarande skapa bibliotek med Visual Studio, och om det är din föredragna upplevelse kan du läsa Visual Studio-guiden.
Förutsättningar
Du behöver .NET SDK installerat på datorn.
För avsnitten i det här dokumentet som hanterar .NET Framework-versioner behöver du .NET Framework installerat på en Windows-dator.
Om du vill stödja äldre .NET Framework-mål måste du dessutom installera målpaket eller utvecklarpaket från nedladdningssidan för .NET Framework. Se den här tabellen:
| .NET Framework-version | Vad du ska ladda ned | 
|---|---|
| 4.6.1 | Målpaket för .NET Framework 4.6.1 | 
| 4,6 | .NET Framework 4.6-målpaket | 
| 4.5.2 | .NET Framework 4.5.2 Utvecklarpaket | 
| 4.5.1 | .NET Framework 4.5.1 Utvecklarpaket | 
| 4,5 | Windows Software Development Kit för Windows 8 | 
| 4.0 | Windows SDK för Windows 7 och .NET Framework 4 | 
| 2.0, 3.0 och 3.5 | .NET Framework 3.5 SP1 Runtime (eller Windows 8+ version) | 
Så här riktar du in dig på .NET 5+ eller .NET Standard
Du styr projektets målramverk genom att lägga till det i projektfilen (.csproj eller .fsproj). Information om hur du väljer mellan att rikta in sig på .NET 5+ eller .NET Standard finns i .NET 5+ och .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>
Om du vill rikta in dig på .NET Framework version 4.0 eller senare, eller om du vill använda ett API som är tillgängligt i .NET Framework men inte i .NET Standard (till exempel System.Drawing), läser du följande avsnitt och lär dig hur du multitarget.
Så här riktar du in dig på .NET Framework
Anteckning
Dessa instruktioner förutsätter att du har .NET Framework installerat på datorn. Se Förutsättningar för att få beroenden installerade.
Tänk på att vissa av de .NET Framework-versioner som används här inte längre stöds. Läs vanliga frågor och svar om versioner som inte stöds i .NET Framework Support Lifecycle Policy.
Om du vill nå det maximala antalet utvecklare och projekt använder du .NET Framework 4.0 som baslinjemål. Börja med att använda rätt Target Framework Moniker (TFM) som motsvarar den .NET Framework-version som du vill stödja för att rikta in dig på .NET Framework.
| .NET Framework-version | 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 | 
Sedan infogar du den här TFM:en i TargetFramework avsnittet i projektfilen. Så här skriver du till exempel ett bibliotek som riktar sig till .NET Framework 4.0:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net40</TargetFramework>
  </PropertyGroup>
</Project>
Det var det! Även om detta endast kompilerades för .NET Framework 4 kan du använda biblioteket i nyare versioner av .NET Framework.
Så här gör du för att sikta på flera mål
Anteckning
Följande instruktioner förutsätter att du har .NET Framework installerat på datorn. Läs avsnittet Förutsättningar för att lära dig vilka beroenden du behöver installera och var du kan ladda ned dem från.
Du kan behöva rikta in dig på äldre versioner av .NET Framework när projektet stöder både .NET Framework och .NET. Om du i det här scenariot vill använda nyare API:er och språkkonstruktioner för de nyare målen använder #if du direktiv i koden. Du kan också behöva lägga till olika paket och beroenden för varje plattform som du riktar in dig på för att inkludera de olika API:er som behövs för varje ärende.
Anta till exempel att du har ett bibliotek som utför nätverksåtgärder via HTTP. För .NET Standard och .NET Framework version 4.5 eller senare kan du använda HttpClient klassen från System.Net.Http namnområdet. Tidigare versioner av .NET Framework har dock inte HttpClient-klassen, så du kan använda WebClient-klassen från namnområdet System.Net i stället.
Projektfilen kan se ut så här:
<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>
Du kommer att märka tre större ändringar här:
- Noden TargetFrameworkhar ersatts avTargetFrameworksoch tre TFM uttrycks inuti.
- Det finns en <ItemGroup>nod förnet40målet som hämtar en referens till .NET Framework.
- Det finns en <ItemGroup>nod för målet därnet45hämtar in två .NET Framework-referenser.
Preprocessorsymboler
Byggsystemet är medvetet om följande preprocessorsymboler som används i #if direktiv:
| Målramverk | Symboler | Ytterligare symboler (finns i .NET 5+ SDK:er) | Plattformssymboler (endast tillgängliga när du anger en OS-specifik TFM) | 
|---|---|---|---|
| .NET Framework | NETFRAMEWORK,NET481,NET48,NET472,NET471,NET47,NET462,NET461,NET46, ,NET452,NET451,NET45,NET40, ,NET35NET20 | NET48_OR_GREATER,NET472_OR_GREATER,NET471_OR_GREATER,NET47_OR_GREATER,NET462_OR_GREATER,NET461_OR_GREATER,NET46_OR_GREATER,NET452_OR_GREATER, ,NET451_OR_GREATER,NET45_OR_GREATER,NET40_OR_GREATER, , ,NET35_OR_GREATERNET20_OR_GREATER | |
| .NET Standard | NETSTANDARD,NETSTANDARD2_1,NETSTANDARD2_0,NETSTANDARD1_6,NETSTANDARD1_5,NETSTANDARD1_4, ,NETSTANDARD1_3,NETSTANDARD1_2, ,NETSTANDARD1_1NETSTANDARD1_0 | NETSTANDARD2_1_OR_GREATER,NETSTANDARD2_0_OR_GREATER,NETSTANDARD1_6_OR_GREATER,NETSTANDARD1_5_OR_GREATER,NETSTANDARD1_4_OR_GREATER,NETSTANDARD1_3_OR_GREATER, ,NETSTANDARD1_2_OR_GREATER, ,NETSTANDARD1_1_OR_GREATERNETSTANDARD1_0_OR_GREATER | |
| .NET 5+ (och .NET Core) | NET,NET9_0,NET8_0,NET7_0,NET6_0,NET5_0,NETCOREAPP,NETCOREAPP3_1,NETCOREAPP3_0,NETCOREAPP2_2,NETCOREAPP2_1,NETCOREAPP2_0,NETCOREAPP1_1NETCOREAPP1_0 | NET9_0_OR_GREATER,NET8_0_OR_GREATER,NET7_0_OR_GREATER,NET6_0_OR_GREATER,NET5_0_OR_GREATER,NETCOREAPP3_1_OR_GREATER,NETCOREAPP3_0_OR_GREATER,NETCOREAPP2_2_OR_GREATER, ,NETCOREAPP2_1_OR_GREATER,NETCOREAPP2_0_OR_GREATER, , ,NETCOREAPP1_1_OR_GREATERNETCOREAPP1_0_OR_GREATER | ANDROID,BROWSER,IOS,MACCATALYST,MACOS, ,TVOS, ,WINDOWS[OS][version](till exempelIOS15_1),[OS][version]_OR_GREATER(till exempelIOS15_1_OR_GREATER) | 
Anteckning
- Versionslösa symboler definieras oavsett vilken version du riktar in dig på.
- Versionsspecifika symboler definieras endast för den version som du riktar in dig på.
- Symbolerna <framework>_OR_GREATERdefinieras för den version som du riktar in dig på och alla tidigare versioner. Om du till exempel riktar in dig på .NET Framework 2.0 definieras följande symboler:NET20,NET20_OR_GREATER,NET11_OR_GREATERochNET10_OR_GREATER.
- Symbolerna NETSTANDARD<x>_<y>_OR_GREATERdefinieras endast för .NET Standard-mål och inte för mål som implementerar .NET Standard, till exempel .NET Core och .NET Framework.
- Dessa skiljer sig från målramverksmoniker (TFM) som används av MSBuild-egenskapen och NuGet.
Här är ett exempel på användning av villkorsstyrd kompilering per mål:
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
    }
}
Om du skapar det här projektet med dotnet buildser du tre kataloger under bin/ mappen:
net40/
net45/
netstandard2.0/
Var och en av dessa innehåller .dll-filerna för varje mål.
Testa bibliotek på .NET
Det är viktigt att kunna testa på olika plattformar. Du kan använda xUnit eller MSTest direkt. Båda passar perfekt för enhetstestning av biblioteket på .NET. Hur du konfigurerar din lösning med testprojekt beror på lösningens struktur. I följande exempel förutsätts att test- och källkatalogerna finns i samma toppnivåkatalog.
Anteckning
Detta använder vissa .NET CLI-kommandon . Mer information finns i dotnet new och dotnet sln .
- Konfigurera din lösning. Du kan göra det med följande kommandon: - 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- Detta skapar projekt och kopplar samman dem i en lösning. Din katalog för - SolutionWithSrcAndTestbör se ut så här:- /SolutionWithSrcAndTest |__SolutionWithSrcAndTest.sln |__MyProject/ |__MyProject.Test/
- Navigera till testprojektets katalog och lägg till en referens till - MyProject.Testfrån- MyProject.- cd MyProject.Test dotnet reference add ../MyProject/MyProject.csproj
- Återställa paket och bygga projekt - dotnet restore dotnet build
- Kontrollera att xUnit körs genom att - dotnet testköra kommandot. Om du väljer att använda MSTest ska MSTest-konsollöparen köras i stället.
Det var det! Nu kan du testa biblioteket på alla plattformar med hjälp av kommandoradsverktyg. Om du vill fortsätta testa nu när allt har konfigurerats är det mycket enkelt att testa biblioteket:
- Gör ändringar i biblioteket.
- Kör tester från kommandoraden i testkatalogen med dotnet testkommandot .
Koden återskapas automatiskt när du anropar dotnet test kommandot.
Så här använder du flera projekt
Ett vanligt behov av större bibliotek är att placera funktioner i olika projekt.
Anta att du vill skapa ett bibliotek som kan användas i idiomatiska C# och F#. Det skulle innebära att användarna av biblioteket använder det på ett sätt som är naturligt för C# eller F#. I C# kan du till exempel använda biblioteket så här:
using AwesomeLibrary.CSharp;
public Task DoThings(Data data)
{
    var convertResult = await AwesomeLibrary.ConvertAsync(data);
    var result = AwesomeLibrary.Process(convertResult);
    // do something with result
}
I F# kan det se ut så här:
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
}
Förbrukningsscenarier som detta innebär att DE API:er som används måste ha en annan struktur för C# och F#. En vanlig metod för att åstadkomma detta är att ta med all logik i ett bibliotek i ett kärnprojekt, med C#- och F#-projekt som definierar DE API-lager som anropar till kärnprojektet. Resten av avsnittet använder följande namn:
- AwesomeLibrary.Core – ett kärnprojekt som innehåller all logik för biblioteket
- AwesomeLibrary.CSharp – ett projekt med offentliga API:er avsedda för förbrukning i C#
- AwesomeLibrary.FSharp – ett projekt med offentliga API:er avsedda för förbrukning i F#
Du kan köra följande kommandon i terminalen för att skapa samma struktur som den här guiden:
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
Detta lägger till de tre projekten ovan och en lösningsfil som länkar ihop dem. Genom att skapa lösningsfilen och länka projekt kan du återställa och skapa projekt från en toppnivå.
Projekt-till-projekt-referens
Det bästa sättet att referera till ett projekt är att använda .NET CLI för att lägga till en projektreferens. Från projektkatalogerna AwesomeLibrary.CSharp och AwesomeLibrary.FSharp kan du köra följande kommando:
dotnet reference add ../AwesomeLibrary.Core/AwesomeLibrary.Core.csproj
Projektfilerna för både AwesomeLibrary.CSharp och AwesomeLibrary.FSharp refererar nu till AwesomeLibrary.Core som mål ProjectReference .  Du kan kontrollera detta genom att granska projektfilerna och se följande i dem:
<ItemGroup>
  <ProjectReference Include="..\AwesomeLibrary.Core\AwesomeLibrary.Core.csproj" />
</ItemGroup>
Du kan lägga till det här avsnittet i varje projektfil manuellt om du föredrar att inte använda .NET CLI.
Strukturera en lösning
En annan viktig aspekt av lösningar för flera projekt är att upprätta en bra övergripande projektstruktur. Du kan ordna kod hur du vill, och så länge du länkar varje projekt till lösningsfilen med dotnet sln addkan du köra dotnet restore och dotnet build på lösningsnivå.