AppContext AppContext AppContext AppContext Class

定义

提供用于设置和检索应用程序上下文相关数据的成员。Provides members for setting and retrieving data about an application's context.

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

注解

AppContext类使库编写器可为其用户提供统一的新功能选择退出机制。The AppContext class enables library writers to provide a uniform opt-out mechanism for new functionality for their users. 它在组件之间建立松耦合的协定,以便与选择退出请求进行通信。It establishes a loosely-coupled contract between components in order to communicate an opt-out request. 对现有功能进行更改时,此功能通常很重要。This capability is typically important when a change is made to existing functionality. 相反,已有新功能隐式选择加入。Conversely, there is already an implicit opt-in for new functionality.

库开发人员的 AppContextAppContext for library developers

库使用AppContext类来定义和公开兼容性切换,而库用户可以设置这些开关以影响库行为。Libraries use the AppContext class to define and expose compatibility switches, while library users can set those switches to affect the library behavior. 默认情况下,库提供新功能;如果设置了开关,则只更改新功能(即,它们提供以前的功能)。By default, libraries provide the new functionality, and they only alter it (that is, they provide the previous functionality) if the switch is set. 这使得库以同时继续支持依赖于以前的行为的调用方提供的现有 API 的新行为。This allows libraries to provide new behavior for an existing API while continuing to support callers who depend on the previous behavior.

定义的开关名称Defining the switch name

允许您的使用者可以选择不使用的更改的最常见方法是行为的库的定义命名的开关。The most common way to allow consumers of your library to opt out of a change of behavior is to define a named switch. value元素都是名称/值对组成开关的名称并将其Boolean值。Its value element is a name/value pair that consists of the name of a switch and its Boolean value. 默认情况下,此开关它始终隐式false,它提供了新的行为 (和参加使得新行为,默认情况下)。By default, the switch is always implicitly false, which provides the new behavior (and makes the new behavior opt-in by default). 此开关设置为true启用它,它提供的旧行为。Setting the switch to true enables it, which provides the legacy behavior. 此开关显式设置为false还提供了新行为。Explicitly setting the switch to false also provides the new behavior.

最好交换机名称,因为它们是由库公开的正式协定中使用一致的格式。It's beneficial to use a consistent format for switch names, since they are a formal contract exposed by a library. 以下是两种明显的格式。The following are two obvious formats.

  • Switch.namespace.switchnameSwitch.namespace.switchname

  • Switch.library.switchnameSwitch.library.switchname

一旦定义并记录该交换机,调用方可以使用它通过使用注册表中,通过添加 <AppContextSwitchOverrides >元素到其应用程序配置文件,或通过调用AppContext.SetSwitch(String, Boolean)方法以编程方式。Once you define and document the switch, callers can use it by using the registry, by adding an <AppContextSwitchOverrides> element to their application configuration file, or by calling the AppContext.SetSwitch(String, Boolean) method programmatically. 请参阅库的使用者的 AppContext详细了解如何调用方使用和设置的值部分AppContext配置切换。See the AppContext for library consumers section for more information about how callers use and set the value of AppContext configuration switches.

当公共语言运行时运行的应用程序时,它会自动读取注册表的兼容性设置并加载应用程序配置文件以填充应用程序的AppContext实例。When the common language runtime runs an application, it automatically reads the registry's compatibility settings and loads the application configuration file in order to populate the application's AppContext instance. 因为AppContext实例已填充以编程方式调用方或运行时,不需要采取任何操作,例如,调用SetSwitch方法,以配置AppContext实例。Because the AppContext instance is populated either programmatically by the caller or by the runtime, you do not have to take any action, such as calling the SetSwitch method, to configure the AppContext instance.

检查设置Checking the setting

然后,可以选中使用者已声明的值的交换机和通过调用适当的 actAppContext.TryGetSwitch方法。You can then check if a consumer has declared the value of the switch and act appropriately by calling the AppContext.TryGetSwitch method. 该方法返回true如果switchName找到参数,并且该方法返回时,将其isEnabled参数指示开关的值。The method returns true if the switchName argument is found, and when the method returns, its isEnabled argument indicates the value of the switch. 否则,该方法将返回 falseOtherwise, the method returns false.

示例An example

下面的示例演示如何使用AppContext类,以允许客户选择的库方法的原始行为。The following example illustrates the use of the AppContext class to allow the customer to choose the original behavior of a library method. 下面是一个名为库的 1.0 版StringLibraryThe following is version 1.0 of a library named StringLibrary. 它定义SubstringStartsAt方法执行序号比较来确定更大的字符串中的子字符串的起始索引。It defines a SubstringStartsAt method that performs an ordinal comparison to determine the starting index of a substring within a larger string.

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);
   }
}
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

下面的示例然后使用库中"archaeologist"查找"archæ"的子字符串的起始索引。The following example then uses the library to find the starting index of the substring "archæ" in "The archaeologist". 由于该方法执行序号比较,因此不能找到子字符串。Because the method performs an ordinal comparison, the substring cannot be found.

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'
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 的库,但是,当更改SubstringStartsAt要使用区分区域性的比较方法。Version 2 of the library, however, changes the SubstringStartsAt method to use culture-sensitive comparison.

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);
   }
}
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æ""archaeologist"中的索引 4 处找到。When the app is recompiled to run against the new version of the library, it now reports that the substring "archæ" is found at index 4 in "The archaeologist".

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   
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

此更改可以防止通过定义取决于原始行为的应用程序的重大 <AppContextSwitchOverrides >切换。This change can be prevented from breaking the applications that depend on the original behavior by defining an <AppContextSwitchOverrides> switch. 在这种情况下,名为开关StringLibrary.DoNotUseCultureSensitiveComparisonIn this case, the switch is named StringLibrary.DoNotUseCultureSensitiveComparison. 其默认值, false,指示库应执行其 2.0 版区分区域性的比较。Its default value, false, indicates that the library should perform its version 2.0 culture-sensitive comparison. true 指示库应执行其版本 1.0 序号比较。true indicates that the library should perform its version 1.0 ordinal comparison. 稍作修改,前面的代码允许设置开关,用于确定的方法不会执行的比较类型的库使用方。A slight modification of the previous code allows the library consumer to set the switch to determine the kind of comparison the method performs.

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);
         
   }
}
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

如果应用程序然后可以使用下面的配置文件来还原版本 1.0 的行为。If application can then use the following configuration file to restore the version 1.0 behavior.


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

应用程序运行时使用的配置文件存在,它将生成以下输出:When the application is run with the configuration file present, it produces the following output:

'archæ' not found in 'The archaeologist'  

库的使用者的 AppContextAppContext for library consumers

如果您是一个库,使用者AppContext类使您可以利用的库或库方法的新功能的选择退出机制。If you are the consumer of a library, the AppContext class allows you to take advantage of a library or library method's opt-out mechanism for new functionality. 正在调用的类库的单个方法定义特定的开关启用或禁用新行为。Individual methods of the class library that you are calling define particular switches that enable or disable a new behavior. 开关的值是一个布尔值。The value of the switch is a Boolean. 如果它是false,这通常是默认值、 启用新行为; 如果它是true、 禁用新行为,并且该成员的行为就像以前一样。If it is false, which is typically the default value, the new behavior is enabled; if it is true, the new behavior is disabled, and the member behaves as it did previously.

可以在四种方法之一来设置开关的值:You can set the value of a switch in one of four ways:

  • 通过调用AppContext.SetSwitch(String, Boolean)在代码中的方法。By calling the AppContext.SetSwitch(String, Boolean) method in your code. switchName参数定义交换机名称和isEnabled属性定义开关的值。The switchName argument defines the switch name, and the isEnabled property defines the value of the switch. 因为AppContext是一个静态类,它是可在每个应用程序域基础上。Because AppContext is a static class, it is available on a per-application domain basis.

    调用AppContext.SetSwitch(String, Boolean)具有应用程序的作用域; 也就是说,它会影响只有应用程序。Calling the AppContext.SetSwitch(String, Boolean) has application scope; that is, it affects only the application.

  • 通过添加<AppContextSwitchOverrides>元素<运行时 > app.config 文件的部分。By adding an <AppContextSwitchOverrides> element to the <runtime> section of your app.config file. 交换机具有单个属性value,其值是一个字符串,表示包含开关的名称和值的键/值对。The switch has a single attribute, value, whose value is a string that represents a key/value pair containing both the switch name and its value.

    若要定义多个开关,单独的每个开关中的键/值对 <AppContextSwitchOverrides >元素的value以分号结尾的属性。To define multiple switches, separate each switch's key/value pair in the <AppContextSwitchOverrides> element's value attribute with a semicolon. 在这种情况下,<AppContextSwitchOverrides>元素具有以下格式:In that case, the <AppContextSwitchOverrides> element has the following format:

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

    使用<AppContextSwitchOverrides>元素来定义配置设置应用程序作用域; 也就是说,它会影响只有应用程序。Using the <AppContextSwitchOverrides> element to define a configuration setting has application scope; that is, it affects only the application.

    备注

    .NET Framework 定义的开关的信息,请参阅 <AppContextSwitchOverrides > 元素For information on the switches defined by the .NET Framework, see the <AppContextSwitchOverrides> element.

  • 通过将其名称是交换机的名称的字符串值添加到HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext密钥在注册表中。By adding a string value whose name is the name of the switch to the HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext key in the registry. 其值必须为字符串表示形式Boolean,则可以通过分析Boolean.Parse方法; 即,它必须为"True","true","False"或"false"。Its value must be the string representation of a Boolean that can be parsed by the Boolean.Parse method; that is, it must be "True", "true", "False", or "false". 如果运行时遇到任何其他值,它将忽略此开关。If the runtime encounters any other value, it ignores the switch.

    使用注册表来定义AppContext交换机具有计算机范围; 即,它会影响计算机上运行每个应用程序。Using the registry to define an AppContext switch has machine scope; that is, it affects every application running on the machine.

  • 对于 ASP.NET 应用程序,您将添加<添加 >元素 <appSettings > web.config 文件部分。For ASP.NET applications, you add an <Add> element to the <appSettings> section of the web.config file. 例如:For example:

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

如果在多个方面中设置相同的开关,用于确定哪些设置会重写其他顺序是优先的:If you set the same switch in more than one way, the order of precedence for determining which setting overrides the others is:

  1. 以编程方式设置。The programmatic setting.

  2. 应用程序配置文件或 web.config 文件中的设置。The setting in the app config file or the web.config file.

  3. 注册表设置。The registry setting.

下面是简单的应用程序将文件 URI 传递到Path.GetDirectoryName方法。The following is a simple application that passes a file URI to the Path.GetDirectoryName method. 当.NET Framework 4.6 下运行,它将引发ArgumentException因为file://不再是有效的部件的文件路径。When run under the .NET Framework 4.6, it throws an ArgumentException because file:// is no longer a valid part of a file path.

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()
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切换到应用程序配置文件。 例如:To restore the method's previous behavior and prevent the exception, you can add the Switch.System.IO.UseLegacyPathHandling switch to the application configuration file for the example:

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

请参阅See also

AppContext 开关AppContext switch

属性

BaseDirectory BaseDirectory BaseDirectory BaseDirectory

获取程序集解析程序用于探测程序集的基目录的路径名。Gets the pathname of the base directory that the assembly resolver uses to probe for assemblies.

TargetFrameworkName TargetFrameworkName TargetFrameworkName TargetFrameworkName

获取当前应用程序所针对的框架版本的名称。Gets the name of the framework version targeted by the current application.

方法

GetData(String) GetData(String) GetData(String) GetData(String)

返回分配给当前应用程序域的已命名数据元素的值。Returns the value of the named data element assigned to the current application domain.

SetSwitch(String, Boolean) SetSwitch(String, Boolean) SetSwitch(String, Boolean) SetSwitch(String, Boolean)

设置开关的值。Sets the value of a switch.

TryGetSwitch(String, Boolean) TryGetSwitch(String, Boolean) TryGetSwitch(String, Boolean) TryGetSwitch(String, Boolean)

尝试获取开关的值。Tries to get the value of a switch.

适用于

另请参阅