System.AppContext 類別

本文提供此 API 參考文件的補充備註。

類別可讓連結 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 應用程式不需要採取任何動作,例如呼叫 SetSwitch 方法,來設定AppContext實例。

檢查設定

您可以檢查取用者是否已宣告參數的值,並藉由呼叫 AppContext.TryGetSwitch 方法來適當地採取行動。 如果switchName找到自變數,則方法會true傳回 ,而其isEnabled自變數表示參數的值。 否則,方法會傳回 false

範例

下列範例說明 如何使用 AppContext 類別,讓客戶選擇連結庫方法的原始行為。 以下是名為 StringLibrary的連結庫 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

當應用程式重新編譯以針對新版本的連結庫執行時,它現在報告在「考古學家」索引 4 中發現了子字串 「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

您可以藉由定義參數,防止中斷相依於原始行為的應用程式。 在這裡情況下,參數會命名為 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表示包含參數名稱和其值的索引鍵/值組。

    若要定義多個參數,請使用分號分隔 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 應用程式,您可以將 Add> 元素新增<至< web.config 檔案的 app 設定> 區段來設定參數。 例如:

<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 應用程式)。

另請參閱