System.AppContext-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

Mit der AppContext Klasse können Bibliotheksautoren einen einheitlichen Opt-Out-Mechanismus für neue Funktionen für ihre Benutzer bereitstellen. Es richtet einen lose gekoppelten Vertrag zwischen den Komponenten ein, um eine Anforderung zur Abwahl zu übermitteln. Diese Möglichkeit ist in der Regel wichtig, wenn vorhandene Funktionalitäten verändert werden. Im Gegensatz dazu existiert bereits eine implizite Auswahloption für neue Funktionalitäten.

AppContext für Bibliotheksentwickler

Bibliotheken verwenden die AppContext Klasse zum Definieren und Verfügbarmachen von Kompatibilitätsschaltern, während Bibliotheksbenutzer diese Schalter festlegen können, um das Bibliotheksverhalten zu beeinflussen. Standardmäßig stellen Bibliotheken die neue Funktionalität bereit. Nur wenn die Option festgelegt ist, stellen sie die vorherige Funktionalität bereit. Dadurch können Bibliotheken ein neues Verhalten für eine vorhandene API bereitstellen und gleichzeitig Aufrufer unterstützen, die vom vorherigen Verhalten abhängig sind.

Definieren des Switchnamens

Die am häufigsten verwendete Möglichkeit, Verbrauchern Ihrer Bibliothek das Deaktivieren einer Verhaltensänderung zu ermöglichen, besteht darin, einen benannten Schalter zu definieren. Das value Element ist ein Name/Wert-Paar, das aus dem Namen eines Schalters und dessen Boolean Wert besteht. Standardmäßig ist die Option immer implizit false, die das neue Verhalten bereitstellt (und das neue Verhalten standardmäßig aktiviert). Durch Festlegen des Schalters auf true diese Option wird das Legacyverhalten ermöglicht. Das explizite Festlegen des Schalters auf false das neue Verhalten wird ebenfalls bereitgestellt.

Es ist vorteilhaft, ein einheitliches Format für Switchnamen zu verwenden, da sie ein formaler Vertrag sind, der von einer Bibliothek verfügbar gemacht wird. Es folgen zwei offensichtliche Formate:

  • Switch.namespace.switchname
  • Switch.library.switchname

Nachdem Sie den Switch definiert und dokumentiert haben, können Aufrufer ihn durch programmgesteuertes Aufrufen der AppContext.SetSwitch(String, Boolean) Methode verwenden. .NET Framework-Apps können den Switch auch verwenden, indem ein <AppContextSwitchOverrides-Element> zu ihrer Anwendungskonfigurationsdatei oder mithilfe der Registrierung hinzugefügt wird. Weitere Informationen zur Verwendung und Festlegung des Werts von AppContext Konfigurationsoptionen finden Sie im Abschnitt "AppContext für Bibliothekskunden ".

Wenn die Common Language Runtime eine Anwendung ausführt, liest sie in .NET Framework automatisch die Kompatibilitätseinstellungen der Registrierung und lädt die Anwendungskonfigurationsdatei AppContext , um die Instanz der Anwendung aufzufüllen. Da die AppContext Instanz entweder programmgesteuert vom Aufrufer oder von der Laufzeit aufgefüllt wird, müssen .NET Framework-Apps keine Aktion ausführen, z. B. das Aufrufen der SetSwitch Methode, um die AppContext Instanz zu konfigurieren.

Überprüfen der Einstellung

Sie können überprüfen, ob ein Verbraucher den Wert des Schalters deklariert und entsprechend reagiert hat, indem Sie die AppContext.TryGetSwitch Methode aufrufen. Die Methode gibt zurück true , wenn das switchName Argument gefunden wird, und das isEnabled Argument gibt den Wert des Schalters an. Andernfalls gibt diese Methode false zurück.

Beispiel

Im folgenden Beispiel wird die Verwendung der Klasse veranschaulicht, mit der AppContext der Kunde das ursprüngliche Verhalten einer Bibliotheksmethode auswählen kann. Die folgende Version ist Version 1.0 einer Bibliothek mit dem Namen StringLibrary. Sie definiert eine SubstringStartsAt Methode, die einen Ordinalvergleich durchführt, um den Anfangsindex einer Teilzeichenfolge innerhalb einer größeren Zeichenfolge zu bestimmen.

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

Im folgenden Beispiel wird dann die Bibliothek verwendet, um den Anfangsindex der Teilzeichenfolge "archæ" in "The archæ" zu finden. Da die Methode einen Ordinalvergleich durchführt, kann die Teilzeichenfolge nicht gefunden werden.

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("'{0}' found in '{1}' starting at position {2}",
                           substring, value, position);
        else
            Console.WriteLine("'{0}' not found in '{1}'", substring, 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'

Version 2.0 der Bibliothek ändert jedoch die SubstringStartsAt Methode, um kultursensitiven Vergleich zu verwenden.

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

Wenn die App für die neue Version der Bibliothek neu kompiliert wird, meldet sie nun, dass die Teilzeichenfolge "archæ" unter Index 4 in "The archäsist" gefunden wird.

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("'{0}' found in '{1}' starting at position {2}",
                           substring, value, position);
        else
            Console.WriteLine("'{0}' not found in '{1}'", substring, 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

Diese Änderung kann daran gehindert werden, die Anwendungen zu unterbrechen, die vom ursprünglichen Verhalten abhängig sind, indem sie einen Schalter definieren. In diesem Fall wird der Schalter benannt StringLibrary.DoNotUseCultureSensitiveComparison. Der Standardwert gibt an, falsedass die Bibliothek einen kulturabhängigen Vergleich der Version 2.0 durchführen soll. true gibt an, dass die Bibliothek den Vergleich der Version 1.0 durchführen soll. Eine geringfügige Änderung des vorherigen Codes ermöglicht es dem Bibliotheksanwender, den Schalter festzulegen, um die Art des Vergleichs zu bestimmen, den die Methode ausführt.

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

Eine .NET Framework-Anwendung kann dann die folgende Konfigurationsdatei verwenden, um das Verhalten der Version 1.0 wiederherzustellen.

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

Wenn die Anwendung mit der vorhandenen Konfigurationsdatei ausgeführt wird, erzeugt sie die folgende Ausgabe:

'archæ' not found in 'The archaeologist'

AppContext für Bibliothekskunden

Wenn Sie der Consumer einer Bibliothek sind, können Sie mit der AppContext Klasse den Opt-Out-Mechanismus einer Bibliothek oder Bibliotheksmethode für neue Funktionen nutzen. Einzelne Methoden der Klassenbibliothek, die Sie aufrufen, definieren bestimmte Schalter, die ein neues Verhalten aktivieren oder deaktivieren. Der Wert des Schalters ist ein Boolescher Wert. Wenn dies falseder Standardwert ist, wird das neue Verhalten aktiviert. Ist dies der Grund, wird truedas neue Verhalten deaktiviert, und das Element verhält sich wie zuvor.

Sie können den Wert einer Option festlegen, indem Sie die AppContext.SetSwitch(String, Boolean) Methode in Ihrem Code aufrufen. Das switchName Argument definiert den Switchnamen, und die isEnabled Eigenschaft definiert den Wert des Schalters. Da AppContext es sich um eine statische Klasse handelt, ist sie pro Anwendung verfügbar Standard. Das Aufrufen des AppContext.SetSwitch(String, Boolean) Anwendungsbereichs hat, d. h., es wirkt sich nur auf die Anwendung aus.

.NET Framework-Apps haben zusätzliche Möglichkeiten zum Festlegen des Werts einer Option:

  • Durch Hinzufügen eines <AppContextSwitchOverrides> Elements zum <Laufzeitabschnitt> der Datei "app.config". Die Option verfügt über ein einzelnes Attribut, valuedessen Wert eine Zeichenfolge ist, die ein Schlüssel-Wert-Paar darstellt, das sowohl den Switchnamen als auch den Wert enthält.

    Um mehrere Schalter zu definieren, trennen Sie das Schlüssel-Wert-Paar jedes Schalters im Attribut des <value AppContextSwitchOverrides-Elements> durch ein Semikolon. In diesem Fall weist das <AppContextSwitchOverrides> Element das folgende Format auf:

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

    Das Verwenden des <AppContextSwitchOverrides> Elements zum Definieren einer Konfigurationseinstellung weist den Anwendungsbereich auf. Das heißt, es wirkt sich nur auf die Anwendung aus.

    Hinweis

    Informationen zu den durch .NET Framework definierten Switches finden Sie unter <"AppContextSwitchOverrides> "-Element.

  • Durch Hinzufügen eines Eintrags zur Registrierung. Fügen Sie dem HKLM\SOFTWARE\Microsoft\einen neuen Zeichenfolgenwert hinzu. NETFramework\AppContext-Unterschlüssel . Legen Sie den Namen des Eintrags auf den Namen der Option fest. Legen Sie den Wert auf eine der folgenden Optionen fest: True, , , true, Falseoder false. Wenn die Laufzeit auf einen anderen Wert trifft, wird der Schalter ignoriert.

    Auf einem 64-Bit-Betriebssystem müssen Sie auch denselben Eintrag zum HKLM\SOFTWARE\Wow6432Node\Microsoft\hinzufügen. NETFramework\AppContext-Unterschlüssel .

    Die Verwendung der Registrierung zum Definieren eines AppContext Switchs weist einen Computerbereich auf. Das heißt, es wirkt sich auf jede Anwendung aus, die auf dem Computer ausgeführt wird.

Für ASP.NET und ASP.NET Core-Anwendungen legen Sie einen Schalter fest, indem Sie der< App ein <Add-Element> hinzufügen Einstellungen> Abschnitt der Datei "web.config" hinzufügen. Beispiel:

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

Wenn Sie denselben Schalter auf mehr als eine Weise festlegen, ist die Reihenfolge der Rangfolge für die Bestimmung, welche Einstellung die anderen Außerkraftsetzungen überschreibt:

  1. Die programmgesteuerte Einstellung.
  2. Die Einstellung in der Datei "app.config" (für .NET Framework-Apps) oder der Datei "web.config" (für ASP.NET Core-Apps).
  3. Die Registrierungseinstellung (nur für .NET Framework-Apps).

Siehe auch