System.AppContext classe
Este artigo fornece observações complementares à documentação de referência para essa API.
A AppContext classe permite que os escritores de biblioteca forneçam um mecanismo de exclusão uniforme para novas funcionalidades para seus usuários. Ela estabelece um contrato flexível entre componentes a fim de comunicar uma solicitação de recusa. Normalmente, essa funcionalidade é importante quando uma alteração é feita na funcionalidade existente. Por outro lado, já existe uma aceitação implícita da nova funcionalidade.
AppContext para desenvolvedores de bibliotecas
As bibliotecas usam a AppContext classe para definir e expor opções de compatibilidade, enquanto os usuários da biblioteca podem definir essas opções para afetar o comportamento da biblioteca. Por padrão, as bibliotecas fornecem a nova funcionalidade, e apenas a alteram (ou seja, eles fornecem a funcionalidade anterior) se a opção for definida. Isso permite que as bibliotecas forneçam um novo comportamento para uma API existente enquanto continuam a oferecer suporte a chamadores que dependem do comportamento anterior.
Definir o nome do switch
A maneira mais comum de permitir que os consumidores de sua biblioteca optem por não participar de uma mudança de comportamento é definir um switch nomeado. Seu value
elemento é um par nome/valor que consiste no nome de um switch e seu Boolean valor. Por padrão, a opção é sempre implicitamente false
, o que fornece o novo comportamento (e torna o novo comportamento opt-in por padrão). Definir o switch para true
habilitá-lo, o que fornece o comportamento herdado. Definir explicitamente a opção para false
também fornece o novo comportamento.
É benéfico usar um formato consistente para alternar nomes, já que eles são um contrato formal exposto por uma biblioteca. A seguir estão dois formatos óbvios:
- Opção.namespace.nomedaopção
- Opção.biblioteca.nomedaopção
Depois de definir e documentar o switch, os chamadores podem usá-lo chamando o AppContext.SetSwitch(String, Boolean) método programaticamente. Os aplicativos do .NET Framework também podem usar a opção adicionando um <elemento AppContextSwitchOverrides ao arquivo de configuração do> aplicativo ou usando o Registro. Para obter mais informações sobre como os chamadores usam e definem o valor das opções de configuração, consulte a seção AppContext para consumidores de AppContext biblioteca.
No .NET Framework, quando o Common Language Runtime executa um aplicativo, ele lê automaticamente as configurações de compatibilidade do Registro e carrega o arquivo de configuração do aplicativo para preencher a instância do AppContext aplicativo. Como a instância é preenchida programaticamente pelo chamador ou pelo tempo de execução, os aplicativos do .NET Framework não precisam executar nenhuma ação, como chamar o SetSwitch método, para configurar a AppContextAppContext instância.
Verifique a configuração
Você pode verificar se um consumidor declarou o valor do switch e agir adequadamente chamando o AppContext.TryGetSwitch método. O método retorna true
se o argumento for encontrado e seu isEnabled
argumento indica o switchName
valor da opção. Do contrário, o método retorna false
.
Exemplo
O exemplo a seguir ilustra o uso da AppContext classe para permitir que o cliente escolha o comportamento original de um método de biblioteca. A seguir está a versão 1.0 de uma biblioteca chamada StringLibrary
. Ele define um SubstringStartsAt
método que executa uma comparação ordinal para determinar o índice inicial de uma subcadeia de caracteres dentro de uma cadeia de caracteres maior.
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
O exemplo a seguir usa a biblioteca para localizar o índice inicial da subcadeia de caracteres "archæ" em "O arqueólogo". Como o método executa uma comparação ordinal, a substring não pode ser encontrada.
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'
A versão 2.0 da biblioteca, no entanto, altera o método para usar a comparação sensível à SubstringStartsAt
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 o aplicativo é recompilado para ser executado contra a nova versão da biblioteca, ele agora relata que a substring "archæ" é encontrada no índice 4 em "O arqueólogo".
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
Essa alteração pode ser impedida de quebrar os aplicativos que dependem do comportamento original definindo uma opção. Nesse caso, a opção é chamada StringLibrary.DoNotUseCultureSensitiveComparison
. Seu valor padrão, , false
indica que a biblioteca deve executar sua comparação sensível à cultura da versão 2.0. true
indica que a biblioteca deve executar sua comparação ordinal da versão 1.0. Uma pequena modificação do código anterior permite que o consumidor da biblioteca defina a opção para determinar o tipo de comparação que o método executa.
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
Um aplicativo .NET Framework pode usar o seguinte arquivo de configuração para restaurar o comportamento da versão 1.0.
<configuration>
<runtime>
<AppContextSwitchOverrides value="StringLibrary.DoNotUseCultureSensitiveComparison=true" />
</runtime>
</configuration>
Quando o aplicativo é executado com o arquivo de configuração presente, ele produz a seguinte saída:
'archæ' not found in 'The archaeologist'
AppContext para consumidores de bibliotecas
Se você for o consumidor de uma biblioteca, a AppContext classe permitirá que você aproveite o mecanismo de desativação de uma biblioteca ou método de biblioteca para novas funcionalidades. Os métodos individuais da biblioteca de classes que você está chamando definem opções específicas que habilitam ou desabilitam um novo comportamento. O valor do switch é booleano. Se for , que normalmente é o valor padrão, o novo comportamento será habilitado, se for false
true
, o novo comportamento será desabilitado e o membro se comportará como antes.
Você pode definir o valor de uma opção chamando o AppContext.SetSwitch(String, Boolean) método em seu código. O switchName
argumento define o nome da opção e a isEnabled
propriedade define o valor da opção. Como AppContext é uma classe estática, ela está disponível por domínio de aplicativo. Chamar o tem escopo de aplicativo, ou seja, afeta apenas o AppContext.SetSwitch(String, Boolean) aplicativo.
Os aplicativos do .NET Framework têm maneiras adicionais de definir o valor de uma opção:
Adicionando um
<AppContextSwitchOverrides>
elemento à <seção de tempo de execução> do arquivo app.config. O switch tem um único atributo,value
, cujo valor é uma cadeia de caracteres que representa um par chave/valor que contém o nome do switch e seu valor.Para definir várias opções, separe o <par chave/valor de cada switch no atributo do elemento AppContextSwitchOverrides>
value
com ponto-e-vírgula. Nesse caso, o elemento tem o<AppContextSwitchOverrides>
seguinte formato:<AppContextSwitchOverrides value="switchName1=value1;switchName2=value2" />
Usar o elemento para definir uma definição de configuração tem escopo de aplicativo, ou seja, afeta apenas o
<AppContextSwitchOverrides>
aplicativo.Observação
Para obter informações sobre as opções definidas pelo .NET Framework, consulte <AppContextSwitchOverrides> elemento.
Adicionando uma entrada ao registro. Adicione um novo valor de cadeia de caracteres ao HKLM\SOFTWARE\Microsoft\. NETFramework\AppContext subchave. Defina o nome da entrada como o nome do switch. Defina seu valor como uma das seguintes opções:
True
, ,true
False
oufalse
. Se o tempo de execução encontrar qualquer outro valor, ele ignorará a opção.Em um sistema operacional de 64 bits, você também deve adicionar a mesma entrada ao HKLM\SOFTWARE\Wow6432Node\Microsoft\. NETFramework\AppContext subchave.
Usar o registro para definir um AppContext switch tem escopo de máquina, ou seja, afeta todos os aplicativos em execução na máquina.
Para aplicativos ASP.NET e ASP.NET Core, defina uma opção adicionando um <elemento Add> à <seção appSettings> do arquivo web.config. Por exemplo:
<appSettings>
<add key="AppContext.SetSwitch:switchName1" value="switchValue1" />
<add key="AppContext.SetSwitch:switchName2" value="switchValue2" />
</appSettings>
Se você definir a mesma opção de mais de uma maneira, a ordem de precedência para determinar qual configuração substitui as outras será:
- A configuração programática.
- A configuração no arquivo app.config (para aplicativos .NET Framework) ou no arquivo web.config (para aplicativos ASP.NET Core).
- A configuração do Registro (somente para aplicativos do .NET Framework).