Clase System.AppContext

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

La AppContext clase permite a los escritores de bibliotecas proporcionar un mecanismo uniforme de exclusión para la nueva funcionalidad para sus usuarios. Establece un contrato flexible entre los componentes para poder comunicar una solicitud de cancelación de la participación. Esta capacidad normalmente es importante cuando se realiza un cambio en la funcionalidad existente. Por el contrario, la nueva funcionalidad participa de forma implícita.

AppContext para desarrolladores de bibliotecas

Las bibliotecas usan la AppContext clase para definir y exponer modificadores de compatibilidad, mientras que los usuarios de biblioteca pueden establecer esos modificadores para que afecten al comportamiento de la biblioteca. De forma predeterminada, las bibliotecas proporcionan la nueva funcionalidad y solo la modifican (es decir, ofrecen la funcionalidad anterior) si el modificador está establecido. Esto permite que las bibliotecas proporcionen un nuevo comportamiento para una API existente mientras siguen admitiendo a los autores de llamadas que dependen del comportamiento anterior.

Definir el nombre del modificador

La manera más común de permitir que los consumidores de la biblioteca opten por no participar en un cambio de comportamiento es definir un modificador con nombre. Su value elemento es un par nombre-valor que consta del nombre de un modificador y su Boolean valor. De forma predeterminada, el modificador siempre es implícitamente false, que proporciona el nuevo comportamiento (y hace que el nuevo comportamiento opt-in de forma predeterminada). Al establecer el modificador true en se habilita , que proporciona el comportamiento heredado. Al establecer explícitamente el modificador false en también se proporciona el nuevo comportamiento.

Es beneficioso usar un formato coherente para los nombres de modificador, ya que son un contrato formal expuesto por una biblioteca. A continuación se muestran dos formatos obvios:

  • Modificador.espacio de nombres.nombre del modificador
  • Modificador.biblioteca.nombre del modificador

Una vez que defina y documente el modificador, los autores de llamadas pueden usarlo mediante una llamada al AppContext.SetSwitch(String, Boolean) método mediante programación. Las aplicaciones de .NET Framework también pueden usar el modificador agregando un <elemento AppContextSwitchOverrides> a su archivo de configuración de aplicación o mediante el registro. Para obtener más información sobre cómo usan los autores de llamadas y establecen el valor de los modificadores de configuración, consulte la sección AppContext para consumidores de AppContext bibliotecas.

En .NET Framework, cuando Common Language Runtime ejecuta una aplicación, lee automáticamente la configuración de compatibilidad del Registro y carga el archivo de configuración de la aplicación para rellenar la instancia de la AppContext aplicación. Dado que el autor de la llamada rellena la AppContext instancia mediante programación o el entorno de ejecución, las aplicaciones de .NET Framework no tienen que realizar ninguna acción, como llamar al SetSwitch método , para configurar la AppContext instancia.

Comprobación de la configuración

Puede comprobar si un consumidor ha declarado el valor del modificador y actuar adecuadamente llamando al AppContext.TryGetSwitch método . El método devuelve true si se encuentra el switchName argumento y su isEnabled argumento indica el valor del modificador. De lo contrario, el método devuelve false.

Ejemplo

En el ejemplo siguiente se muestra el uso de la AppContext clase para permitir al cliente elegir el comportamiento original de un método de biblioteca. A continuación se muestra la versión 1.0 de una biblioteca denominada StringLibrary. Define un método que realiza una SubstringStartsAt comparación ordinal para determinar el índice inicial de una subcadena dentro de una cadena mayor.

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

A continuación, en el ejemplo siguiente se usa la biblioteca para buscar el índice inicial de la subcadena "archæ" en "The archæ". Dado que el método realiza una comparación ordinal, no se encuentra la subcadena.

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'

Sin embargo, la versión 2.0 de la biblioteca cambia el método para usar la SubstringStartsAt comparación que distingue la referencia cultural.

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

Cuando se vuelve a compilar la aplicación para ejecutarse con la nueva versión de la biblioteca, ahora informa de que la subcadena "archæ" se encuentra en el índice 4 en "The archæ".

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

Este cambio puede impedirse interrumpir las aplicaciones que dependen del comportamiento original definiendo un modificador. En este caso, el modificador se denomina StringLibrary.DoNotUseCultureSensitiveComparison. Su valor predeterminado, false, indica que la biblioteca debe realizar su comparación de referencia cultural de la versión 2.0. true indica que la biblioteca debe realizar su comparación ordinal de la versión 1.0. Una ligera modificación del código anterior permite al consumidor de biblioteca establecer el modificador para determinar el tipo de comparación que realiza el método.

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

Después, una aplicación de .NET Framework puede usar el siguiente archivo de configuración para restaurar el comportamiento de la versión 1.0.

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

Cuando la aplicación se ejecuta con el archivo de configuración presente, genera la siguiente salida:

'archæ' not found in 'The archaeologist'

AppContext para consumidores de bibliotecas

Si es el consumidor de una biblioteca, la AppContext clase le permite aprovechar el mecanismo de exclusión de una biblioteca o método de biblioteca para la nueva funcionalidad. Los métodos individuales de la biblioteca de clases a la que se llama definen modificadores concretos que habilitan o deshabilitan un nuevo comportamiento. El valor del modificador es un valor booleano. Si es false, que suele ser el valor predeterminado, el nuevo comportamiento está habilitado; si es true, el nuevo comportamiento está deshabilitado y el miembro se comporta como hizo anteriormente.

Puede establecer el valor de un modificador llamando al método en el AppContext.SetSwitch(String, Boolean) código. El switchName argumento define el nombre del modificador y la isEnabled propiedad define el valor del modificador. Dado AppContext que es una clase estática, está disponible por dominio de aplicación. Llamar a AppContext.SetSwitch(String, Boolean) tiene ámbito de aplicación; es decir, afecta solo a la aplicación.

Las aplicaciones de .NET Framework tienen maneras adicionales de establecer el valor de un modificador:

  • Al agregar un <AppContextSwitchOverrides> elemento a la <sección en tiempo de ejecución> del archivo app.config. El modificador tiene un único atributo, value, cuyo valor es una cadena que representa un par clave-valor que contiene el nombre del modificador y su valor.

    Para definir varios modificadores, separe el par clave-valor de cada conmutador en el <atributo del value elemento AppContextSwitchOverrides> con un punto y coma. En ese caso, el <AppContextSwitchOverrides> elemento tiene el siguiente formato:

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

    El uso del <AppContextSwitchOverrides> elemento para definir una configuración tiene ámbito de aplicación; es decir, afecta solo a la aplicación.

    Nota:

    Para obtener información sobre los modificadores definidos por .NET Framework, vea Elemento AppContextSwitchOverrides>.<

  • Mediante la adición de una entrada al Registro. Agregue un nuevo valor de cadena al HKLM\SOFTWARE\Microsoft\. Subclave NETFramework\AppContext . Establezca el nombre de la entrada en el nombre del modificador. Establezca su valor en una de las siguientes opciones: True, true, Falseo false. Si el tiempo de ejecución encuentra cualquier otro valor, omite el modificador.

    En un sistema operativo de 64 bits, también debe agregar la misma entrada a HKLM\SOFTWARE\Wow6432Node\Microsoft\. Subclave NETFramework\AppContext .

    El uso del Registro para definir un AppContext conmutador tiene ámbito de máquina; es decir, afecta a todas las aplicaciones que se ejecutan en la máquina.

Para las aplicaciones ASP.NET y ASP.NET Core, establezca un modificador agregando un <elemento Add> a la <aplicación Configuración> sección del archivo web.config. Por ejemplo:

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

Si establece el mismo modificador en más de una manera, el orden de prioridad para determinar qué configuración invalida a los demás es:

  1. Configuración mediante programación.
  2. La configuración del archivo app.config (para aplicaciones de .NET Framework) o el archivo web.config (para aplicaciones de ASP.NET Core).
  3. Configuración del Registro (solo para aplicaciones de .NET Framework).

Consulte también