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 也會提供新的行為。

使用交換器名稱的一致格式很有説明,因為它們是由程式庫公開的正式合約。 以下是兩種明顯的格式:

  • 參數.命名空間.參數名稱

  • 參數.程式庫.參數名稱

定義並記錄參數之後,呼叫端就可以透過程式設計方式呼叫 AppContext.SetSwitch(String, Boolean) 方法來使用它。 .NET Framework應用程式也可以藉由將元素新增 <AppContextSwitchOverrides> 至其應用程式組態檔或使用登錄,來使用 參數。 如需呼叫端如何使用和設定組態參數值 AppContext 的詳細資訊,請參閱 程式庫取用者的 AppCoNtext 一 節。

當 .NET Framework Common Language Runtime 執行應用程式時,它會自動讀取登錄的相容性設定,並載入應用程式組態檔以填入應用程式的 AppContext 實例。 AppContext由於實例是以程式設計方式填入呼叫端或由.NET Framework執行時間填入,因此.NET Framework應用程式不需要採取任何動作,例如呼叫 SetSwitch 方法,即可設定 AppContext 實例。

檢查設定

您可以檢查取用者是否已宣告參數的值,並藉由呼叫 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

下列範例接著會使用程式庫來尋找 「The archist」 中子字串 「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æ」 位於 「The substrist」 的索引 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應用程式有其他方法來設定參數的值:

  • 將 專案新增 <AppContextSwitchOverrides><runtime> app.config檔案的 區段。 參數具有單一屬性, value 其值為字串,代表包含參數名稱和其值的索引鍵/值組。

    若要定義多個參數,請使用分號分隔元素 value 屬性中的每個 <AppContextSwitchOverrides> 參數索引鍵/值組。 在此情況下, <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應用程式,您可以將 元素新增 <Add><appSettings> web.config檔案的 區段來設定參數。 例如:

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

如果您以多個方式設定相同的參數,則判斷哪些設定會覆寫其他設定的優先順序如下:

  1. 程式設計設定。

  2. app.config檔案 (中.NET Framework應用程式的設定) 或 ASP.NET Core應用程式) 的web.config檔案 (。

  3. 僅) .NET Framework應用程式的登錄設定 (。

以下是將檔案 URI 傳遞至 方法的 Path.GetDirectoryName 簡單應用程式。 在 .NET Framework 4.6 下執行時,會擲回 , ArgumentException 因為 file:// 不再是檔案路徑的有效部分。

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

取得目前應用程式設為目標的 Framework 版本名稱。

方法

GetData(String)

傳回指派給目前應用程式定義域的具名資料元素值。

SetData(String, Object)

設定指派給目前應用程式域之具名資料元素的值。

SetSwitch(String, Boolean)

設定參數的值。

TryGetSwitch(String, Boolean)

嘗試取得參數的值。

適用於

另請參閱