Thanks to visit codestin.com
Credit goes to github.com

Skip to content

System.AppContext F# snippets #7425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Example4

// <Snippet4>
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)

// </Snippet4>

// <Snippet5>
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'
// </Snippet5>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Example6

// <Snippet6>
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)

// </Snippet6>

// <Snippet7>
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
// </Snippet7>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Example8

// <Snippet8>
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)

// </Snippet8>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// <Snippet10>
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@()
// </Snippet10>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\ForConsumers1.fs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module TestValue1

open System

// <Snippet1>
AppContext.SetSwitch("Switch.AmazingLib.ThrowOnException", true)
// </Snippet1>

// <Snippet2>
module AmazingLib =
let performAnOperation () =
match AppContext.TryGetSwitch "Switch.AmazingLib.ThrowOnException" with
| false, _ ->
// This is the case where the switch value was not set by the application.
// The library can choose to get the value of shouldThrow by other means.
// If no overrides or default values are specified, the value should be 'false'.
// A false value implies the latest behavior.
()
| true, shouldThrow ->
// The library can use the value of shouldThrow to throw exceptions or not.
if shouldThrow then
// old code
()
else
// new code
()
// </Snippet2>

AmazingLib.performAnOperation ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="TestValue1.fs" />
<Compile Include="Example4.fs" />
<Compile Include="Example6.fs" />
<Compile Include="Example8.fs" />
<Compile Include="ForConsumers1.fs" />
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions xml/System/AppContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,26 +73,31 @@
The following example illustrates the use of the <xref:System.AppContext> class to allow the customer to choose the original behavior of a library method. The following is version 1.0 of a library named `StringLibrary`. It defines a `SubstringStartsAt` method that performs an ordinal comparison to determine the starting index of a substring within a larger string.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example4.cs" id="Snippet4":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example4.fs" id="Snippet4":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example4.vb" id="Snippet4":::

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.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example4.cs" id="Snippet5":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example4.fs" id="Snippet5":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example4.vb" id="Snippet5":::

Version 2 of the library, however, changes the `SubstringStartsAt` method to use culture-sensitive comparison.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example6.cs" id="Snippet6":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example6.fs" id="Snippet6":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example6.vb" id="Snippet6":::

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

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example6.cs" id="Snippet7":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example6.fs" id="Snippet7":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example6.vb" id="Snippet7":::

This change can be prevented from breaking the applications that depend on the original behavior by defining an [\<AppContextSwitchOverrides>](/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element) switch. In this case, the switch is named `StringLibrary.DoNotUseCultureSensitiveComparison`. Its default value, `false`, indicates that the library should perform its version 2.0 culture-sensitive comparison. `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.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example8.cs" id="Snippet8":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example8.fs" id="Snippet8":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example8.vb" id="Snippet8":::

If application can then use the following configuration file to restore the version 1.0 behavior.
Expand Down Expand Up @@ -162,6 +167,7 @@ If you set the same switch in more than one way, the order of precedence for det
The following is a simple application that passes a file URI to the <xref:System.IO.Path.GetDirectoryName%2A?displayProperty=nameWithType> method. When run under the .NET Framework 4.6, it throws an <xref:System.ArgumentException> because `file://` is no longer a valid part of a file path.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/ForConsumers1.cs" id="Snippet10":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/ForConsumers1.fs" id="Snippet10":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/ForConsumers1.vb" id="Snippet10":::

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:
Expand Down Expand Up @@ -370,6 +376,7 @@ In .NET 5 and later versions, for bundled assemblies, the value returned is the
The following line of code sets a switch named `Switch.AmazingLib.ThrowOnException` to `true`, which enables a legacy behavior. The library can then check whether a library consumer has set the value of the switch by calling the <xref:System.AppContext.TryGetSwitch%2A> method.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/TestValue1.cs" id="Snippet1":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/TestValue1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/TestValue1.vb" id="Snippet1":::

]]></format>
Expand Down Expand Up @@ -494,6 +501,7 @@ In .NET 5 and later versions, for bundled assemblies, the value returned is the
The following example determines whether a library consumer has set a switch named `Switch.AmazingLib.ThrowOnException`.

:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/TestValue1.cs" id="Snippet2":::
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/TestValue1.fs" id="Snippet2":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/TestValue1.vb" id="Snippet2":::

]]></format>
Expand Down