Класс System.AppContext

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Класс AppContext позволяет писателям библиотек предоставлять единый механизм отказа для новых функциональных возможностей для своих пользователей. Он устанавливает слабо связанный контракт между компонентами для передачи запроса на явный отказ. Эта возможность обычно важна при внесении изменений в существующие функции. В свою очередь, режим неявного согласия для новых функциональных возможностей уже существует.

AppContext для разработчиков библиотек

Библиотеки используют AppContext класс для определения и предоставления параметров совместимости, а пользователи библиотеки могут задать эти переключатели, чтобы повлиять на поведение библиотеки. По умолчанию библиотеки предоставляют новые функции и изменяют их (то есть предоставляют прежние функции) только в том случае, если установлен параметр. Это позволяет библиотекам предоставлять новое поведение для существующего API, продолжая поддерживать вызывающих лиц, которые зависят от предыдущего поведения.

Определение имени переключателя

Наиболее распространенный способ разрешить потребителям библиотеки отказаться от изменения поведения — определить именованный коммутатор. Его value элемент — это пара name/value, состоящая из имени коммутатора и его Boolean значения. По умолчанию параметр всегда неявно false, который обеспечивает новое поведение (и делает новое поведение по умолчанию). Если параметр включен true , он обеспечивает устаревшее поведение. Явное задание переключателя false также обеспечивает новое поведение.

Полезно использовать согласованный формат для имен переключения, так как он является формальным контрактом, предоставляемым библиотекой. Ниже приведены два очевидных формата:

  • параметр. пространство_именимя_параметра
  • параметр.библиотека.имя_параметра

После определения и документирования коммутатора вызывающие элементы могут использовать его, вызывая метод программным способом AppContext.SetSwitch(String, Boolean) . платформа .NET Framework приложения также могут использовать переключатель, добавив <Элемент AppContextSwitchOverrides> в файл конфигурации приложения или с помощью реестра. Дополнительные сведения о том, как вызывающие пользователи используют и задают значение AppContext коммутаторов конфигурации, см. в разделе AppContext для потребителей библиотеки.

В платформа .NET Framework, когда среда CLR запускает приложение, она автоматически считывает параметры совместимости реестра и загружает файл конфигурации приложения для заполнения экземпляра AppContext приложения. AppContext Так как экземпляр заполняется либо вызывающим оператором, либо средой выполнения, платформа .NET Framework приложения не должны предпринимать никаких действий, таких как вызов SetSwitch метода, для настройки экземпляраAppContext.

Проверка параметра

Можно проверка, если потребитель объявил значение коммутатора и действовать соответствующим образом, вызвав AppContext.TryGetSwitch метод. Метод возвращает true значение, если switchName аргумент найден, а его isEnabled аргумент указывает значение коммутатора. В противном случае метод возвращает значение false.

Пример

В следующем примере показано использование AppContext класса, позволяющего клиенту выбрать исходное поведение метода библиотеки. Ниже приведена версия 1.0 библиотеки с именем StringLibrary. Он определяет SubstringStartsAt метод, который выполняет порядковое сравнение, чтобы определить начальный индекс подстроки в более крупной строке.

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

В следующем примере библиотека используется для поиска начального индекса подстроки "архе" в "Археолог". Так как метод выполняет порядковое сравнение, подстрока не найдена.

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'

Однако версия 2.0 библиотеки изменяет SubstringStartsAt метод для использования сравнения с учетом языка и региональных параметров.

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

Когда приложение перекомпилируется для запуска с новой версией библиотеки, теперь сообщает, что подстрока "archæ" найдена в индексе 4 в "Археолог".

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

Это изменение может быть запрещено нарушать приложения, зависящие от исходного поведения, определив переключатель. В этом случае переключатель называется StringLibrary.DoNotUseCultureSensitiveComparison. Значение по умолчанию указывает, что библиотека должна выполнять сравнение с учетом языка и региональных параметров falseверсии 2.0. true указывает, что библиотека должна выполнять его порядковое сравнение версии 1.0. Небольшое изменение предыдущего кода позволяет потребителю библиотеки задать параметр для определения типа сравнения, выполняемого методом.

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

Затем приложение платформа .NET Framework может использовать следующий файл конфигурации для восстановления поведения версии 1.0.

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

При запуске приложения с файлом конфигурации он создает следующие выходные данные:

'archæ' not found in 'The archaeologist'

AppContext для потребителей библиотеки

Если вы являетесь потребителем библиотеки, AppContext класс позволяет воспользоваться механизмом отказа библиотеки или метода библиотеки для новых функциональных возможностей. Отдельные методы вызываемой библиотеки классов определяют определенные коммутаторы, которые позволяют включить или отключить новое поведение. Значение параметра — логическое значение. Если это falseзначение обычно является значением по умолчанию, новое поведение включено; если это trueтак, новое поведение отключено, и член ведет себя так, как это было ранее.

Можно задать значение коммутатора, вызвав AppContext.SetSwitch(String, Boolean) метод в коде. Аргумент switchName определяет имя коммутатора, а isEnabled свойство определяет значение коммутатора. Так как AppContext это статический класс, он доступен на основе домена каждого приложения. AppContext.SetSwitch(String, Boolean) Вызов приложения область; т. е. влияет только на приложение.

платформа .NET Framework приложения имеют дополнительные способы задания значения коммутатора:

  • <AppContextSwitchOverrides> Добавив элемент в <раздел среды выполнения> файла app.config. Параметр имеет один атрибут, значение которого представляет пару "ключ-значение", valueсодержащую имя коммутатора и его значение.

    Чтобы определить несколько коммутаторов, разделите пару ключей и значений каждого коммутатора в атрибуте <элемента value AppContextSwitchOverrides> с запятой. В этом случае <AppContextSwitchOverrides> элемент имеет следующий формат:

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

    <AppContextSwitchOverrides> Использование элемента для определения параметра конфигурации имеет приложение область; то есть это влияет только на приложение.

    Примечание.

    Сведения о параметрах, определенных платформа .NET Framework, см<. в элементе AppContextSwitchOverrides>.

  • Добавив запись в реестр. Добавьте новое строковое значение в HKLM\SOFTWARE\Microsoft\. Вложенный ключ NETFramework\AppContext . Задайте имя записи именем переключателя. Задайте для его значения одно из следующих параметров: True, , trueFalseили false. Если среда выполнения обнаруживает любое другое значение, он игнорирует переключатель.

    В 64-разрядной операционной системе необходимо также добавить ту же запись в HKLM\SOFTWARE\Wow6432Node\Microsoft\. Вложенный ключ NETFramework\AppContext .

    С помощью реестра для определения коммутатора AppContext есть компьютер область; то есть это влияет на каждое приложение, работающее на компьютере.

Для приложений ASP.NET и ASP.NET Core установите переключатель путем добавления <элемента Add> в <приложение Параметры> раздела файла web.config. Например:

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

Если один и тот же параметр задан несколькими способами, порядок приоритета для определения того, какой параметр переопределяет другие:

  1. Программный параметр.
  2. Параметр в файле app.config (для приложений платформа .NET Framework) или файла веб.config (для приложений ASP.NET Core).
  3. Параметр реестра (только для приложений платформа .NET Framework).

См. также