Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.
La classe AppContext consente agli scrittori di librerie di fornire un meccanismo uniforme di esclusione per le nuove funzionalità per i loro utenti. Stabilisce un contratto ad accoppiamento debole tra i componenti per comunicare una richiesta di esclusione. Questa funzionalità è in genere importante quando viene apportata una modifica alla funzionalità esistente. Al contrario, esiste già un consenso esplicito implicito per le nuove funzionalità.
AppContext per sviluppatori di librerie
Le librerie usano la classe AppContext per definire ed esporre commutatori di compatibilità, mentre gli utenti della libreria possono impostare tali opzioni per influire sul comportamento della libreria. Per impostazione predefinita, le librerie forniscono le nuove funzionalità e le modificano solo (ovvero forniscono la funzionalità precedente) se l'opzione è impostata. Ciò consente alle librerie di fornire un nuovo comportamento per un'API esistente, continuando a supportare i chiamanti che dipendono dal comportamento precedente.
Definire il nome dell'interruttore
Il modo più comune per consentire ai consumer della libreria di rifiutare esplicitamente una modifica del comportamento consiste nel definire un'opzione denominata. L'elemento value è una coppia nome/valore costituita dal nome di un'opzione e dal relativo valore Boolean. Per impostazione predefinita, l'opzione è sempre implicitamente false, il che introduce il nuovo comportamento (e rende il nuovo comportamento attivo di default). L'impostazione dell'opzione su true lo abilita, che attiva il comportamento legacy. L'impostazione esplicita dell'interruttore su false fornisce anche il nuovo comportamento.
È utile usare un formato coerente per i nomi degli interruttori, perché sono un accordo formale esposto da una libreria. Di seguito sono riportati due formati ovvi:
- Opzione. spazio dei nomi. switchname
- Switch.libreria.switchname
Dopo aver definito e documentare l'opzione, i chiamanti possono usarlo chiamando il metodo AppContext.SetSwitch(String, Boolean) a livello di codice. Le app .NET Framework possono anche usare l'opzione aggiungendo un <AppContextSwitchOverrides> elemento al file di configurazione dell'applicazione o usando il Registro di sistema. Per ulteriori informazioni su come gli utenti utilizzano e impostano il valore delle opzioni di configurazione AppContext, consultare la sezione AppContext per i clienti delle librerie.
In .NET Framework, quando Common Language Runtime esegue un'applicazione, legge automaticamente le impostazioni di compatibilità del Registro di sistema e carica il file di configurazione dell'applicazione per popolare l'istanza di AppContext dell'applicazione. Poiché l'istanza di AppContext viene popolata a livello di codice dal chiamante o dal runtime, le app .NET Framework non devono eseguire alcuna azione, ad esempio chiamando il metodo SetSwitch, per configurare l'istanza di AppContext.
Controllare l'impostazione
È possibile verificare se un consumer ha dichiarato il valore dell'opzione e agire in modo appropriato chiamando il metodo AppContext.TryGetSwitch. Il metodo restituisce true se viene trovato l'argomento switchName e il relativo argomento isEnabled indica il valore dell'opzione. In caso contrario, il metodo restituisce false.
Esempio
Nell'esempio seguente viene illustrato l'uso della classe AppContext per consentire al cliente di scegliere il comportamento originale di un metodo di libreria. Di seguito è riportata la versione 1.0 di una libreria denominata StringLibrary. Definisce un metodo SubstringStartsAt che esegue un confronto ordinale per determinare l'indice iniziale di una sottostringa all'interno di una stringa più grande.
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
L'esempio seguente utilizza quindi la libreria per trovare l'indice iniziale della sottostringa "archæ" in "L'archeologo". Poiché il metodo esegue un confronto ordinale, non è possibile trovare la sottostringa.
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'
La versione 2.0 della libreria, tuttavia, modifica il metodo SubstringStartsAt per usare una comparazione sensibile alla cultura.
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
Quando l'app viene ricompilata per essere eseguita sulla nuova versione della libreria, ora segnala che la sottostringa "archæ" si trova all'indice 4 in "L'archeologo".
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
Questa modifica può essere impedita di compromettere le applicazioni che dipendono dal comportamento originale definendo un'opzione. In questo caso, l'opzione è denominata StringLibrary.DoNotUseCultureSensitiveComparison. Il valore predefinito, false, indica che la libreria deve eseguire un confronto sensibile alla cultura nella versione 2.0.
true indica che la libreria deve eseguire il suo confronto ordinale della versione 1.0. Una leggera modifica del codice precedente consente al consumer della libreria di impostare l'opzione per determinare il tipo di confronto eseguito dal metodo.
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
Un'applicazione .NET Framework può quindi usare il file di configurazione seguente per ripristinare il comportamento della versione 1.0.
<configuration>
<runtime>
<AppContextSwitchOverrides value="StringLibrary.DoNotUseCultureSensitiveComparison=true" />
</runtime>
</configuration>
Quando l'applicazione viene eseguita con il file di configurazione presente, genera l'output seguente:
'archæ' not found in 'The archaeologist'
AppContext per gli utenti di librerie
Se si è l'utilizzatore di una libreria, la classe AppContext consente di sfruttare il meccanismo di esclusione di una libreria o di un metodo di libreria per le nuove funzionalità. I singoli metodi della libreria di classi che si stanno chiamando definiscono opzioni specifiche che abilitano o disabilitano un nuovo comportamento. Il valore dell'opzione è un valore booleano. Se è false, che è in genere il valore predefinito, il nuovo comportamento è abilitato; se è true, il nuovo comportamento è disabilitato e il membro si comporta come in precedenza.
È possibile impostare il valore di un'opzione chiamando il metodo AppContext.SetSwitch(String, Boolean) nel codice. L'argomento switchName definisce il nome dell'opzione e la proprietà isEnabled definisce il valore dell'opzione. Poiché AppContext è una classe statica, è disponibile per ogni dominio applicazione. La chiamata al AppContext.SetSwitch(String, Boolean) ha ambito dell'applicazione; ovvero influisce solo sull'applicazione.
Le app .NET Framework hanno modi aggiuntivi per impostare il valore di un'opzione:
Aggiungendo un elemento
<AppContextSwitchOverrides>alla sezione <runtime> del file app.config. L'opzione ha un singolo attributo,value, il cui valore è una stringa che rappresenta una coppia chiave/valore contenente sia il nome dell'opzione che il relativo valore.Per definire più interruttori, separare la coppia chiave/valore di ogni opzione nell'attributo < dell'elemento > con un punto e virgola. In tal caso, l'elemento
<AppContextSwitchOverrides>ha il formato seguente:<AppContextSwitchOverrides value="switchName1=value1;switchName2=value2" />L'uso dell'elemento
<AppContextSwitchOverrides>per definire un'impostazione di configurazione ha un ambito dell'applicazione; ovvero influisce solo sull'applicazione.Nota
Per informazioni sugli interruttori definiti da .NET Framework, vedere <elemento AppContextSwitchOverrides>.
Aggiungendo una voce al Registro di sistema. Aggiungere un nuovo valore stringa al HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext sottochiave. Impostare il nome della voce sul nome dell'interruttore. Impostarne il valore su una delle opzioni seguenti:
True,true,Falseofalse. Se il runtime rileva qualsiasi altro valore, ignora l'opzione.In un sistema operativo a 64 bit è necessario aggiungere anche la stessa voce alla HKLM\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext sottochiave.
L'uso del Registro di sistema per definire un commutatore AppContext ha ambito computer; ovvero influisce su ogni applicazione in esecuzione nel computer.
Per le applicazioni ASP.NET e ASP.NET Core, è possibile impostare un'opzione aggiungendo un elemento <Add> alla sezione <appSettings> del file di web.config. Per esempio:
<appSettings>
<add key="AppContext.SetSwitch:switchName1" value="switchValue1" />
<add key="AppContext.SetSwitch:switchName2" value="switchValue2" />
</appSettings>
Se si imposta lo stesso commutatore in più modi, l'ordine di precedenza per determinare quale impostazione sostituisce le altre è:
- Impostazione programmatica
- L'impostazione nel file app.config (per le app .NET Framework) o nel file web.config (per le app ASP.NET Core).
- Impostazione del Registro di sistema (solo per le app .NET Framework).