다음을 통해 공유


System.AppContext 클래스

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

AppContext 클래스를 사용하면 라이브러리 작성자가 사용자에게 새로운 기능을 위한 균일한 옵트아웃 메커니즘을 제공할 수 있습니다. 옵트아웃(opt out) 요청을 전달하기 위해 구성 요소 간에 느슨하게 결합된 계약을 설정합니다. 이 기능은 일반적으로 기존 기능이 변경될 때 중요합니다. 반대로, 새로운 기능에 대한 암시적 옵트인(opt in)은 이미 있습니다.

라이브러리 개발자를 위한 AppContext

라이브러리는 클래스를 AppContext 사용하여 호환성 스위치를 정의하고 노출하는 반면 라이브러리 사용자는 라이브러리 동작에 영향을 주도록 해당 스위치를 설정할 수 있습니다. 기본적으로 라이브러리는 새로운 기능을 제공하며 스위치가 설정된 경우에만 변경합니다(즉, 이전 기능 제공). 이렇게 하면 라이브러리가 이전 동작에 의존하는 호출자를 계속 지원하면서 기존 API에 대한 새 동작을 제공할 수 있습니다.

스위치 이름 정의

라이브러리 소비자가 동작 변경을 옵트아웃할 수 있도록 하는 가장 일반적인 방법은 명명된 스위치를 정의하는 것입니다. 해당 value 요소는 스위치 Boolean 의 이름과 해당 값으로 구성된 이름/값 쌍입니다. 기본적으로 스위치는 항상 암시적으로 false새 동작을 제공하며 기본적으로 새 동작을 옵트인합니다. 스위치를 사용하도록 설정하면 true 레거시 동작이 제공됩니다. 스위치를 명시적으로 설정하여 false 새 동작도 제공합니다.

라이브러리에서 공개하는 공식 계약이므로 스위치 이름에 일관된 형식을 사용하는 것이 좋습니다. 다음은 두 가지 명백한 형식입니다.

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

스위치를 정의하고 문서화하면 호출자는 메서드를 AppContext.SetSwitch(String, Boolean) 프로그래밍 방식으로 호출하여 사용할 수 있습니다. .NET Framework 앱은 AppContextSwitchOverrides> 요소를 애플리케이션 구성 파일에 추가<하거나 레지스트리를 사용하여 스위치를 사용할 수도 있습니다. 호출자가 구성 스위치의 AppContext 값을 사용하고 설정하는 방법에 대한 자세한 내용은 라이브러리 소비자에 대한 AppContext 섹션을 참조하세요.

.NET Framework에서 공용 언어 런타임이 애플리케이션을 실행하면 레지스트리의 호환성 설정을 자동으로 읽고 애플리케이션 구성 파일을 로드하여 애플리케이션 인스턴스 AppContext 를 채웁니다. AppContext 인스턴스는 호출자 또는 런타임에 의해 프로그래밍 방식으로 채워지므로 .NET Framework 앱은 인스턴스를 구성 AppContext 하기 위해 메서드 호출 SetSwitch 과 같은 작업을 수행할 필요가 없습니다.

설정 확인

소비자가 스위치의 값을 선언한 경우 검사 메서드를 호출하여 적절하게 작동할 AppContext.TryGetSwitch 수 있습니다. 인수가 switchName 발견되면 메서드가 반환 true 되고 해당 isEnabled 인수는 스위치의 값을 나타냅니다. 그렇지 않은 경우 메서드는 false를 반환합니다.

예시

다음 예제에서는 클래스를 사용하여 AppContext 고객이 라이브러리 메서드의 원래 동작을 선택할 수 있도록 하는 방법을 보여 줍니다. 다음은 이름이 StringLibrary1.0인 라이브러리의 버전 1.0입니다. 더 큰 문자열 내에서 하위 문자열의 시작 인덱스를 결정하기 위해 서수 비교를 수행하는 메서드를 정의 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

다음 예제에서는 라이브러리를 사용하여 "고고학자"에서 부분 문자열 "archæ"의 시작 인덱스 찾기를 찾습니다. 메서드가 서수 비교를 수행하므로 부분 문자열을 찾을 수 없습니다.

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 앱에는 스위치의 값을 설정하는 추가 방법이 있습니다.

  • app.config 파일의< 런타임> 섹션에 요소를 추가 <AppContextSwitchOverrides> 합니다. 스위치에는 스위치 이름과 해당 값을 모두 포함하는 키/값 쌍을 나타내는 문자열인 단일 특성 value이 있습니다.

    여러 스위치를 정의하려면 AppContextSwitchOverrides 요소의 특성에서 <각 스위치의 value 키/값 쌍을 세미콜론으로 구분합니다.> 이 경우 요소의 <AppContextSwitchOverrides> 형식은 다음과 같습니다.

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

    사용 하는 <AppContextSwitchOverrides> 구성 설정을 정의 하는 요소에는 애플리케이션 범위에만 애플리케이션에 영향을 주므로,.

    참고 항목

    .NET Framework에서 정의한 스위치에 대한 자세한 내용은 AppContextSwitchOverrides 요소를 참조<하세요.>

  • 레지스트리에 항목을 추가합니다. HKLM\SOFTWARE\Microsoft\에 새 문자열 값을 추가합니다. NETFramework\AppContext 하위 키입니다. 항목의 이름을 스위치 이름으로 설정합니다. 해당 값을 다음 옵션 TruetrueFalsefalse중 하나로 설정합니다. 런타임에서 다른 값이 발견되면 스위치를 무시합니다.

    64비트 운영 체제에서는 HKLM\SOFTWARE\Wow6432Node\Microsoft\에도 동일한 항목을 추가해야 합니다. NETFramework\AppContext 하위 키입니다.

    레지스트리를 사용 하 여 정의 하는 AppContext 스위치 컴퓨터 범위에는 컴퓨터에서 실행 중인 모든 애플리케이션에 영향을 주므로, 합니다.

ASP.NET 및 ASP.NET Core 애플리케이션의 경우 web.config 파일의 앱설정> 섹션에< Add> 요소를 추가하여 <스위치를 설정합니다. 예시:

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

둘 이상의 방법으로 동일한 스위치를 설정하는 경우 다른 설정을 재정의하는 우선 순위는 다음과 같습니다.

  1. 프로그래밍 방식 설정입니다.
  2. app.config 파일(.NET Framework 앱의 경우) 또는 web.config 파일(ASP.NET Core 앱의 경우)의 설정입니다.
  3. 레지스트리 설정(.NET Framework 앱에만 해당).

참고 항목