AppContext クラス

定義

アプリケーションのコンテキストについてのデータを設定したり取得したりするためのメンバーを提供します。

public ref class AppContext abstract sealed
public static class AppContext
type AppContext = class
Public Class AppContext
継承
AppContext

注釈

この AppContext クラスを使用すると、ライブラリ ライターは、ユーザーの新機能に対して統一されたオプトアウト メカニズムを提供できます。 これにより、オプトアウト要求を伝達するために、コンポーネント間に疎結合のコントラクトが確立されます。 通常、この機能は既存の機能が変更されるときに重要となります。 それに対して、新しい機能には暗黙のオプトインが既に存在しています。

ライブラリ開発者向けの AppContext

ライブラリはクラスを AppContext 使用して互換性スイッチを定義および公開しますが、ライブラリ ユーザーはこれらのスイッチを設定してライブラリの動作に影響を与えることができます。 ライブラリは、既定では新しい機能を提供し、スイッチが設定されている場合のみそれを変更する (つまり以前の機能を提供する) ことができます。 これにより、ライブラリは既存の API に新しい動作を提供しながら、以前の動作に依存する呼び出し元を引き続きサポートできます。

スイッチ名を定義する

ライブラリのコンシューマーが動作の変更をオプトアウトできるようにする最も一般的な方法は、名前付きスイッチを定義することです。 その value 要素は、スイッチの名前とその Boolean 値で構成される名前と値のペアです。 既定では、スイッチは常に暗黙的に false行われ、新しい動作が提供されます (また、新しい動作は既定でオプトインされます)。 スイッチを有効にするように true 設定すると、従来の動作が提供されます。 スイッチを明示的に設定すると false 、新しい動作も提供されます。

スイッチ名はライブラリによって公開される正式なコントラクトであるため、スイッチ名に一貫した形式を使用すると便利です。 2 つの明白な形式を次に示します。

  • Switch.namespace.switchname

  • Switch.library.switchname

スイッチを定義して文書化すると、呼び出し元はプログラムでメソッドを呼び出すことでスイッチを AppContext.SetSwitch(String, Boolean) 使用できます。 .NET Frameworkアプリでは、アプリケーション構成ファイルに要素を追加するか、レジストリを<AppContextSwitchOverrides>使用してスイッチを使用することもできます。 呼び出し元が構成スイッチの値を使用して設定する方法の AppContext 詳細については、 ライブラリ コンシューマーの AppContext に関する セクションを参照してください。

.NET Framework共通言語ランタイムは、アプリケーションを実行すると、レジストリの互換性設定を自動的に読み取り、アプリケーション構成ファイルを読み込んでアプリケーションのAppContextインスタンスを設定します。 AppContextインスタンスは呼び出し元または.NET Framework ランタイムによってプログラムによって設定されるため、.NET Framework アプリは、インスタンスを構成AppContextするためにメソッドのSetSwitch呼び出しなどのアクションを実行する必要はありません。

[この項目を条件付きで表示する] という設定をオンにします

コンシューマーがスイッチの値を宣言しているかどうかを確認し、メソッドを呼び出 AppContext.TryGetSwitch して適切に動作させることができます。 メソッドは、引数がswitchName見つかった場合に返trueし、メソッドが返されるときに、そのisEnabled引数はスイッチの値を示します。 それ以外の場合、メソッドは false を返します。

使用例

次の例では、クラスを AppContext 使用して、お客様がライブラリ メソッドの元の動作を選択できるようにする方法を示します。 次に、名前付きのライブラリのバージョン 1.0 を示します StringLibrary。 より大きな文字列内の部分文字列の開始インデックスを決定するために序数比較を実行するメソッドを定義 SubstringStartsAt します。

using System;
using System.Reflection;

[assembly: AssemblyVersion("1.0.0.0")]

public static class StringLibrary
{
   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 Example
{
   public static void Main()
   {
      string value = "The archaeologist";
      string substring = "archæ";
      int position = StringLibrary.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 Example
   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 StringLibrary
{
   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 Example
{
   public static void Main()
   {
      string value = "The archaeologist";
      string substring = "archæ";
      int position = StringLibrary.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 Example
   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 ファイルのセクションに<runtime>要素を追加<AppContextSwitchOverrides>します。 スイッチには 1 つの属性があり、 valueその値はスイッチ名とその値の両方を含むキーと値のペアを表す文字列です。

    複数のスイッチを定義するには、要素の属性の各スイッチのキーと値のvalueペアを<AppContextSwitchOverrides>セミコロンで区切ります。 その場合、要素の <AppContextSwitchOverrides> 形式は次のとおりです。

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

    この要素を <AppContextSwitchOverrides> 使用して構成設定を定義すると、アプリケーション スコープが設定されます。つまり、アプリケーションにのみ影響します。

    注意

    .NET Frameworkによって定義されたスイッチの詳細については、要素を参照してください<AppContextSwitchOverrides>

  • レジストリにエントリを追加します。 HKLM\SOFTWARE\Microsoft に新しい文字列値を追加 します\。NETFramework\AppContext サブキー。 エントリの名前をスイッチの名前に設定します。 値を次のいずれかのオプションに設定します。 True``true``False``false ランタイムが他の値を検出した場合、スイッチは無視されます。

    64 ビット オペレーティング システムでは、 HKLM\SOFTWARE\Wow6432Node\Microsoft\ にも同じエントリを追加する必要があります。NETFramework\AppContext サブキー。

    レジストリを使用してスイッチを定義すると AppContext 、マシン スコープが設定されます。つまり、マシン上で実行されているすべてのアプリケーションに影響します。

ASP.NET アプリケーションと ASP.NET Core アプリケーションの場合は、web.config ファイルのセクションに要素を追加<Add>して<appSettings>スイッチを設定します。 次に例を示します。

<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 アプリの場合のみ)。

ファイル URI をメソッドに渡す単純なアプリケーションを次に Path.GetDirectoryName 示します。 .NET Framework 4.6 で実行すると、ファイル パスの有効な部分ではなくなったためfile://がスローArgumentExceptionされます。

using System;
using System.IO;
using System.Runtime.Versioning;

[assembly:TargetFramework(".NETFramework,Version=v4.6.2")]

public class Example
{
   public static void Main()
   {
      Console.WriteLine(Path.GetDirectoryName("file://c/temp/dirlist.txt"));
   }
}
// The example displays the following output:
//    Unhandled Exception: System.ArgumentException: The path is not of a legal form.
//       at System.IO.Path.NewNormalizePathLimitedChecks(String path, Int32 maxPathLength, Boolean expandShortPaths)
//       at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
//       at System.IO.Path.InternalGetDirectoryName(String path)
//       at Example.Main()
module Example

open System.IO
open System.Runtime.Versioning

[<assembly: TargetFramework(".NETFramework,Version=v4.6.2")>]
do ()

Path.GetDirectoryName "file://c/temp/dirlist.txt"
|> printfn "%s"


// The example displays the following output:
//    Unhandled Exception: System.ArgumentException: The path is not of a legal form.
//       at System.IO.Path.NewNormalizePathLimitedChecks(String path, Int32 maxPathLength, Boolean expandShortPaths)
//       at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
//       at System.IO.Path.InternalGetDirectoryName(String path)
//       at <StartupCode$ForConsumers1>.$Example.main@()
Imports System.IO
Imports System.Runtime.Versioning

<assembly:TargetFramework(".NETFramework,Version=v4.6.2")>

Module Example
   Public Sub Main()
      Console.WriteLine(Path.GetDirectoryName("file://c/temp/dirlist.txt")) 
   End Sub
End Module
' The example displays the following output:
'    Unhandled Exception: System.ArgumentException: The path is not of a legal form.
'       at System.IO.Path.NewNormalizePathLimitedChecks(String path, Int32 maxPathLength, Boolean expandShortPaths)
'       at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
'       at System.IO.Path.InternalGetDirectoryName(String path)
'       at Example.Main()

メソッドの以前の動作を復元し、例外を回避するには、次の例のアプリケーション構成ファイルにスイッチを追加 Switch.System.IO.UseLegacyPathHandling します。

<configuration>
    <runtime>
        <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=true" />
    </runtime>
</configuration>

関連項目

プロパティ

BaseDirectory

アセンブリを探すためにアセンブリ リゾルバーが使用するベース ディレクトリのファイル パスを取得します。

TargetFrameworkName

現在のアプリケーションの対象となるフレームワークのバージョンの名前を取得します。

メソッド

GetData(String)

現在のアプリケーション ドメインに割り当てられている名前付きデータ要素の値を返します。

SetData(String, Object)

現在のアプリケーション ドメインに割り当てられている名前付きデータ要素の値を設定します。

SetSwitch(String, Boolean)

スイッチの値を設定します。

TryGetSwitch(String, Boolean)

スイッチの値の取得を試みます。

適用対象

こちらもご覧ください