1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ using System ;
5
+ using System . Runtime . CompilerServices ;
6
+
7
+ namespace CommunityToolkit . Mvvm ;
8
+
9
+ /// <summary>
10
+ /// A container for all shared <see cref="AppContext"/> configuration switches for the MVVM Toolkit.
11
+ /// </summary>
12
+ /// <remarks>
13
+ /// <para>
14
+ /// This type uses a very specific setup for configuration switches to ensure ILLink can work the best.
15
+ /// This mirrors the architecture of feature switches in the runtime as well, and it's needed so that
16
+ /// no static constructor is generated for the type.
17
+ /// </para>
18
+ /// <para>
19
+ /// For more info, see <see href="https://github.com/dotnet/runtime/blob/main/docs/workflow/trimming/feature-switches.md#adding-new-feature-switch"/>.
20
+ /// </para>
21
+ /// </remarks>
22
+ internal static class FeatureSwitches
23
+ {
24
+ /// <summary>
25
+ /// The configuration property name for <see cref="EnableINotifyPropertyChangingSupport"/>.
26
+ /// </summary>
27
+ private const string EnableINotifyPropertyChangingSupportPropertyName = "MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT" ;
28
+
29
+ /// <summary>
30
+ /// The backing field for <see cref="EnableINotifyPropertyChangingSupport"/>.
31
+ /// </summary>
32
+ private static int enableINotifyPropertyChangingSupport ;
33
+
34
+ /// <summary>
35
+ /// Gets a value indicating whether or not support for <see cref="System.ComponentModel.INotifyPropertyChanging"/> should be enabled (defaults to <see langword="true"/>).
36
+ /// </summary>
37
+ public static bool EnableINotifyPropertyChangingSupport
38
+ {
39
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
40
+ get => GetConfigurationValue ( EnableINotifyPropertyChangingSupportPropertyName , ref enableINotifyPropertyChangingSupport , true ) ;
41
+ }
42
+
43
+ /// <summary>
44
+ /// Gets a configuration value for a specified property.
45
+ /// </summary>
46
+ /// <param name="propertyName">The property name to retrieve the value for.</param>
47
+ /// <param name="cachedResult">The cached result for the target configuration value.</param>
48
+ /// <param name="defaultValue">The default value for the feature switch, if not set.</param>
49
+ /// <returns>The value of the specified configuration setting.</returns>
50
+ private static bool GetConfigurationValue ( string propertyName , ref int cachedResult , bool defaultValue )
51
+ {
52
+ // The cached switch value has 3 states:
53
+ // 0: unknown.
54
+ // 1: true
55
+ // -1: false
56
+ //
57
+ // This method doesn't need to worry about concurrent accesses to the cached result,
58
+ // as even if the configuration value is retrieved twice, that'll always be the same.
59
+ if ( cachedResult < 0 )
60
+ {
61
+ return false ;
62
+ }
63
+
64
+ if ( cachedResult > 0 )
65
+ {
66
+ return true ;
67
+ }
68
+
69
+ // Get the configuration switch value, or its default.
70
+ // All feature switches have a default set in the .targets file.
71
+ if ( ! AppContext . TryGetSwitch ( propertyName , out bool isEnabled ) )
72
+ {
73
+ isEnabled = defaultValue ;
74
+ }
75
+
76
+ // Update the cached result
77
+ cachedResult = isEnabled ? 1 : - 1 ;
78
+
79
+ return isEnabled ;
80
+ }
81
+ }
0 commit comments