Delen via


System.AppContext-klasse

In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.

Met de AppContext-klasse kunnen bibliotheekschrijvers een uniform opt-outmechanisme bieden voor nieuwe functionaliteit voor hun gebruikers. Er wordt een losjes gekoppeld contract tussen componenten tot stand gebracht om een opt-out-aanvraag te communiceren. Deze mogelijkheid is doorgaans belangrijk wanneer een wijziging wordt aangebracht in bestaande functionaliteit. Omgekeerd is er al een impliciete opt-in voor nieuwe functionaliteit.

AppContext voor bibliotheekontwikkelaars

Bibliotheken gebruiken de AppContext-klasse om compatibiliteitsswitches te definiëren en beschikbaar te maken, terwijl bibliotheekgebruikers deze switches kunnen instellen om het gedrag van de bibliotheek te beïnvloeden. Bibliotheken bieden standaard de nieuwe functionaliteit en ze wijzigen deze alleen (dat wil gezegd, ze bieden de vorige functionaliteit) als de switch is ingesteld. Hierdoor kunnen bibliotheken nieuw gedrag bieden voor een bestaande API, terwijl bellers die afhankelijk zijn van het vorige gedrag blijven ondersteunen.

De naam van de switch definiëren

De meest voorkomende manier om gebruikers van uw bibliotheek in staat te stellen zich te afmelden voor een wijziging van het gedrag, is door een benoemde switch te definiëren. Het value element is een naam/waardepaar dat bestaat uit de naam van een switch en de bijbehorende Boolean waarde. Standaard staat de switch altijd impliciet op false, wat het nieuwe gedrag biedt (en het nieuwe gedrag standaard inschakelt). Door de schakelaar op true te zetten, wordt deze ingeschakeld, wat zorgt voor het verouderde gedrag. Het expliciet instellen van de schakelaar op false biedt ook het nieuwe gedrag.

Het is handig om een consistente indeling te gebruiken voor switchnamen, omdat ze een formeel contract zijn dat wordt weergegeven door een bibliotheek. Hieronder ziet u twee voor de hand liggende indelingen:

  • Switch.naamruimte.switchnaam
  • Switch.bibliotheek.switchnaam

Zodra u de schakeloptie hebt gedefinieerd en gedocumenteerd, kunnen aanroepers deze gebruiken door de methode AppContext.SetSwitch(String, Boolean) programmatisch aan te roepen. .NET Framework-apps kunnen de schakeloptie ook gebruiken door een <AppContextSwitchOverrides> element toe te voegen aan hun toepassingsconfiguratiebestand of door het register te gebruiken. Zie de sectie AppContext voor meer informatie over hoe bellers de waarde van configuratieswitches gebruiken en instellen.

Wanneer in .NET Framework een toepassing wordt uitgevoerd door de algemene taalruntime, worden de compatibiliteitsinstellingen van het register automatisch gelezen en wordt het toepassingsconfiguratiebestand geladen om het AppContext exemplaar van de toepassing te vullen. Omdat het AppContext exemplaar programmatisch wordt ingevuld door de aanroeper of door de runtime, hoeven .NET Framework-apps geen actie te ondernemen, zoals het aanroepen van de SetSwitch methode, om het AppContext-exemplaar te configureren.

De instelling controleren

U kunt controleren of een consument de waarde van de switch heeft gedeclareerd en op de juiste wijze heeft gehandeld door de methode AppContext.TryGetSwitch aan te roepen. De methode retourneert true als het argument switchName wordt gevonden en het bijbehorende isEnabled argument geeft de waarde van de schakeloptie aan. Anders geeft de methode falseterug.

Voorbeeld

In het volgende voorbeeld ziet u het gebruik van de AppContext-klasse, zodat de klant het oorspronkelijke gedrag van een bibliotheekmethode kan kiezen. Hieronder ziet u versie 1.0 van een bibliotheek met de naam StringLibrary. Hiermee wordt een SubstringStartsAt methode gedefinieerd waarmee een rangtelvergelijking wordt uitgevoerd om de beginindex van een subtekenreeks binnen een grotere tekenreeks te bepalen.

using System;
using System.Reflection;

[assembly: AssemblyVersion("1.0.0.0")]

public static class StringLibrary1
{
    public static int SubstringStartsAt(string fullString, string substr)
    {
        return fullString.IndexOf(substr, StringComparison.Ordinal);
    }
}
open System
open System.Reflection

[<assembly: AssemblyVersion("1.0.0.0")>]
do ()

module StringLibrary =
    let substringStartsAt (fullString: string) (substr: string) =
        fullString.IndexOf(substr, StringComparison.Ordinal)
Imports System.Reflection

<Assembly: AssemblyVersion("1.0.0.0")>

Public Class StringLibrary
   Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
      Return fullString.IndexOf(substr, StringComparison.Ordinal)
   End Function
End Class

In het volgende voorbeeld wordt vervolgens de bibliotheek gebruikt om de beginindex van de subtekenreeks "archæ" te vinden in "De archeoloog". Omdat de methode een rangtelvergelijking uitvoert, kan de subtekenreeks niet worden gevonden.

using System;

public class Example1
{
    public static void Main()
    {
        string value = "The archaeologist";
        string substring = "archæ";
        int position = StringLibrary1.SubstringStartsAt(value, substring);
        if (position >= 0)
            Console.WriteLine($"'{substring}' found in '{value}' starting at position {position}");
        else
            Console.WriteLine($"'{substring}' not found in '{value}'");
    }
}
// The example displays the following output:
//       'archæ' not found in 'The archaeologist'
let value = "The archaeologist"
let substring = "archæ"

let position =
    StringLibrary.substringStartsAt value substring

if position >= 0 then
    printfn $"'{substring}' found in '{value}' starting at position {position}"
else
    printfn $"'{substring}' not found in '{value}'"

// The example displays the following output:
//       'archæ' not found in 'The archaeologist'
Public Module Example4
    Public Sub Main()
        Dim value As String = "The archaeologist"
        Dim substring As String = "archæ"
        Dim position As Integer = StringLibrary.SubstringStartsAt(value, substring)
        If position >= 0 Then
            Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
                        substring, value, position)
        Else
            Console.WriteLine("'{0}' not found in '{1}'", substring, value)
        End If
    End Sub
End Module
' The example displays the following output:
'       'archæ' not found in 'The archaeologist'

Versie 2.0 van de bibliotheek wijzigt echter de methode SubstringStartsAt om cultuurgevoelige vergelijking te gebruiken.

using System;
using System.Reflection;

[assembly: AssemblyVersion("2.0.0.0")]

public static class StringLibrary2
{
    public static int SubstringStartsAt(string fullString, string substr)
    {
        return fullString.IndexOf(substr, StringComparison.CurrentCulture);
    }
}
open System
open System.Reflection

[<assembly: AssemblyVersion("2.0.0.0")>]
do ()

module StringLibrary =
    let substringStartsAt (fullString: string) (substr: string) =
        fullString.IndexOf(substr, StringComparison.CurrentCulture)
Imports System.Reflection

<Assembly: AssemblyVersion("2.0.0.0")>

Public Class StringLibrary
   Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
      Return fullString.IndexOf(substr, StringComparison.CurrentCulture)
   End Function
End Class

Wanneer de app opnieuw wordt gecompileerd om te worden uitgevoerd op de nieuwe versie van de bibliotheek, wordt nu gerapporteerd dat de subtekenreeks "archæ" is gevonden op index 4 in "de archeoloog".

using System;

public class Example2
{
    public static void Main()
    {
        string value = "The archaeologist";
        string substring = "archæ";
        int position = StringLibrary2.SubstringStartsAt(value, substring);
        if (position >= 0)
            Console.WriteLine($"'{substring}' found in '{value}' starting at position {position}");
        else
            Console.WriteLine($"'{substring}' not found in '{value}'");
    }
}
// The example displays the following output:
//       'archæ' found in 'The archaeologist' starting at position 4
let value = "The archaeologist"
let substring = "archæ"

let position =
    StringLibrary.substringStartsAt value substring

if position >= 0 then
    printfn $"'{substring}' found in '{value}' starting at position {position}"
else
    printfn $"'{substring}' not found in '{value}'"

// The example displays the following output:
//       'archæ' found in 'The archaeologist' starting at position 4
Public Module Example6
    Public Sub Main()
        Dim value As String = "The archaeologist"
        Dim substring As String = "archæ"
        Dim position As Integer = StringLibrary.SubstringStartsAt(value, substring)
        If position >= 0 Then
            Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
                        substring, value, position)
        Else
            Console.WriteLine("'{0}' not found in '{1}'", substring, value)
        End If
    End Sub
End Module
' The example displays the following output:
'       'archæ' found in 'The archaeologist' starting at position 4

Deze wijziging kan worden voorkomen dat de toepassingen die afhankelijk zijn van het oorspronkelijke gedrag, worden onderbroken door een switch te definiëren. In dit geval heeft de switch de naam StringLibrary.DoNotUseCultureSensitiveComparison. De standaardwaarde, false, geeft aan dat de bibliotheek de cultuurgevoelige vergelijking van versie 2.0 moet uitvoeren. true geeft aan dat de bibliotheek de ordinale vergelijking van versie 1.0 moet uitvoeren. Met een kleine wijziging van de vorige code kan de bibliotheekgebruiker de schakeloptie instellen om het soort vergelijking te bepalen dat door de methode wordt uitgevoerd.

using System;
using System.Reflection;

[assembly: AssemblyVersion("2.0.0.0")]

public static class StringLibrary
{
   public static int SubstringStartsAt(string fullString, string substr)
   {
      bool flag;
      if (AppContext.TryGetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison", out flag) && flag == true)
         return fullString.IndexOf(substr, StringComparison.Ordinal);
      else
         return fullString.IndexOf(substr, StringComparison.CurrentCulture);
   }
}
open System
open System.Reflection

[<assembly: AssemblyVersion("2.0.0.0")>]
do ()

AppContext.SetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison",true)

module StringLibrary =
    let substringStartsAt (fullString: string) (substr: string) =
        match AppContext.TryGetSwitch "StringLibrary.DoNotUseCultureSensitiveComparison" with 
        | true, true -> fullString.IndexOf(substr, StringComparison.Ordinal)
        | _ -> fullString.IndexOf(substr, StringComparison.CurrentCulture)
Imports System.Reflection

<Assembly: AssemblyVersion("2.0.0.0")>

Public Class StringLibrary
   Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
      Dim flag As Boolean
      If AppContext.TryGetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison", flag) AndAlso flag = True Then
         Return fullString.IndexOf(substr, StringComparison.Ordinal)
      Else
         Return fullString.IndexOf(substr, StringComparison.CurrentCulture)
      End If   
   End Function
End Class

Een .NET Framework-toepassing kan vervolgens het volgende configuratiebestand gebruiken om het gedrag van versie 1.0 te herstellen.

<configuration>
   <runtime>
      <AppContextSwitchOverrides value="StringLibrary.DoNotUseCultureSensitiveComparison=true" />
   </runtime>
</configuration>

Wanneer de toepassing wordt uitgevoerd met het configuratiebestand dat aanwezig is, wordt de volgende uitvoer gegenereerd:

'archæ' not found in 'The archaeologist'

AppContext voor bibliotheekgebruikers

Als u de consument bent van een bibliotheek, kunt u met de AppContext-klasse gebruikmaken van het opt-outmechanisme van een bibliotheek of bibliotheekmethode voor nieuwe functionaliteit. Afzonderlijke methoden van de klassenbibliotheek die u aanroept, definiëren bepaalde schakelopties die een nieuw gedrag in- of uitschakelen. De waarde van de switch is een Booleaanse waarde. Als het falseis, wat doorgaans de standaardwaarde is, wordt het nieuwe gedrag ingeschakeld; als het trueis, wordt het nieuwe gedrag uitgeschakeld en gedraagt het lid zich zoals eerder is gedaan.

U kunt de waarde van een switch instellen door de AppContext.SetSwitch(String, Boolean) methode in uw code aan te roepen. Het argument switchName definieert de naam van de switch en de eigenschap isEnabled definieert de waarde van de switch. Omdat AppContext een statische klasse is, is deze beschikbaar per toepassingsdomein. Het aanroepen van de AppContext.SetSwitch(String, Boolean) heeft toepassingsgebied; dat wil zeggen, dit is van invloed op slechts de toepassing.

.NET Framework-apps hebben extra manieren om de waarde van een switch in te stellen:

  • Door een <AppContextSwitchOverrides> element toe te voegen aan de <runtime> sectie van het app.config-bestand. De schakelaar heeft één kenmerk, value, waarvan de waarde een tekenreeks is die een sleutel-waardepaar vertegenwoordigt dat zowel de naam van de schakelaar als de waarde bevat.

    Als u meerdere schakelopties wilt definiëren, scheidt u het sleutel-waardepaar van elke switch in het kenmerk van <AppContextSwitchOverrides> het value element met een puntkomma. In dat geval heeft het <AppContextSwitchOverrides> element de volgende indeling:

    <AppContextSwitchOverrides value="switchName1=value1;switchName2=value2" />
    

    Het <AppContextSwitchOverrides>-element gebruiken om een configuratie-instelling te definiëren, heeft toepassingsbereik; Dat wil gezegd, dit is alleen van invloed op de toepassing.

    Notitie

    Voor informatie over de switches die zijn gedefinieerd door .NET Framework, zie het element <AppContextSwitchOverrides>.

  • Door een vermelding toe te voegen aan het register. Voeg een nieuwe tekenreekswaarde toe aan de HKLM\SOFTWARE\Microsoft\. NETFramework\AppContext subsleutel. Stel de naam van de ingave in op de naam van de schakelaar. Stel de waarde ervan in op een van de volgende opties: True, true, Falseof false. Als de runtime een andere waarde tegenkomt, wordt de switch genegeerd.

    Op een 64-bits besturingssysteem moet u ook dezelfde vermelding toevoegen aan de HKLM\SOFTWARE\Wow6432Node\Microsoft\. NETFramework\AppContext subsleutel.

    Het register gebruiken om een AppContext switch te definiëren heeft een machinebereik; Dat wil gezegd, dit is van invloed op elke toepassing die op de computer wordt uitgevoerd.

Voor ASP.NET- en ASP.NET Core-toepassingen stelt u een schakeloptie in door een <Add> element toe te voegen aan de <appSettings> sectie van het web.config-bestand. Voorbeeld:

<appSettings>
   <add key="AppContext.SetSwitch:switchName1" value="switchValue1" />
   <add key="AppContext.SetSwitch:switchName2" value="switchValue2" />
</appSettings>

Als u dezelfde schakelaar op meerdere manieren instelt, is de prioriteitsvolgorde om te bepalen welke instelling de andere instellingen overschrijft:

  1. De programmatische instelling.
  2. De instelling in het app.config-bestand (voor .NET Framework-apps) of het web.config-bestand (voor ASP.NET Core-apps).
  3. De registerinstelling (alleen voor .NET Framework-apps).

Zie ook