From af55190212bea88204d90bcec251b241a00e03dc Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 17:47:10 -0700 Subject: [PATCH 1/6] Refactor bundled .targets --- ...munityToolkit.Mvvm.FeatureSwitches.targets | 3 + ...unityToolkit.Mvvm.SourceGenerators.targets | 149 +++++++++++++++++ .../CommunityToolkit.Mvvm.csproj | 37 ++++- .../CommunityToolkit.Mvvm.targets | 154 +----------------- 4 files changed, 195 insertions(+), 148 deletions(-) create mode 100644 src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets create mode 100644 src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.SourceGenerators.targets diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets new file mode 100644 index 00000000..4de98b5c --- /dev/null +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.SourceGenerators.targets b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.SourceGenerators.targets new file mode 100644 index 00000000..aa4b8966 --- /dev/null +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.SourceGenerators.targets @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @(MVVMToolkitCurrentCompilerAssemblyIdentity->'%(Version)') + + + true + + + + + + + + + + + + + + true + + + + + + + + + roslyn4.3 + roslyn4.0 + + + + + + + + + + + + + + true + + + + + + + + + + true + + + + + + + \ No newline at end of file diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj index 2c1f713e..e682aa43 100644 --- a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj @@ -91,11 +91,41 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - @(MVVMToolkitCurrentCompilerAssemblyIdentity->'%(Version)') - - - true - - - - - - - - - - - - - - true - - - - - - - - - roslyn4.3 - roslyn4.0 - - - - - - - - - - - - - - true - - - - - - - - - - true - - - - - + + + <_CommunityToolkitMvvmFeatureSwitchesTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.FeatureSwitches.targets + <_CommunityToolkitMvvmSourceGeneratorsTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.SourceGenerators.targets + + + + + \ No newline at end of file From 4cad2e085d59173f3fdecf2b6850966f6d3751c2 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 17:57:33 -0700 Subject: [PATCH 2/6] Refactor switches into 'FeatureSwitches' type --- .../ComponentModel/ObservableObject.cs | 9 ++- .../Properties/Configuration.cs | 37 --------- .../Properties/FeatureSwitches.cs | 81 +++++++++++++++++++ 3 files changed, 89 insertions(+), 38 deletions(-) delete mode 100644 src/CommunityToolkit.Mvvm/Properties/Configuration.cs create mode 100644 src/CommunityToolkit.Mvvm/Properties/FeatureSwitches.cs diff --git a/src/CommunityToolkit.Mvvm/ComponentModel/ObservableObject.cs b/src/CommunityToolkit.Mvvm/ComponentModel/ObservableObject.cs index f3252a29..895f6031 100644 --- a/src/CommunityToolkit.Mvvm/ComponentModel/ObservableObject.cs +++ b/src/CommunityToolkit.Mvvm/ComponentModel/ObservableObject.cs @@ -57,6 +57,12 @@ protected virtual void OnPropertyChanging(PropertyChangingEventArgs e) { ArgumentNullException.ThrowIfNull(e); + // When support is disabled, just do nothing + if (!FeatureSwitches.EnableINotifyPropertyChangingSupport) + { + return; + } + PropertyChanging?.Invoke(this, e); } @@ -75,7 +81,8 @@ protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) /// (optional) The name of the property that changed. protected void OnPropertyChanging([CallerMemberName] string? propertyName = null) { - if (Configuration.IsINotifyPropertyChangingDisabled) + // When support is disabled, avoid instantiating the event args entirely + if (!FeatureSwitches.EnableINotifyPropertyChangingSupport) { return; } diff --git a/src/CommunityToolkit.Mvvm/Properties/Configuration.cs b/src/CommunityToolkit.Mvvm/Properties/Configuration.cs deleted file mode 100644 index d0ca0ade..00000000 --- a/src/CommunityToolkit.Mvvm/Properties/Configuration.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.ComponentModel; - -/// -/// A container for all shared configuration switches for the MVVM Toolkit. -/// -internal static class Configuration -{ - /// - /// The configuration property name for . - /// - private const string DisableINotifyPropertyChangingSupport = "MVVMTOOLKIT_DISABLE_INOTIFYPROPERTYCHANGING"; - - /// - /// Indicates whether or not support for is disabled. - /// - public static readonly bool IsINotifyPropertyChangingDisabled = GetConfigurationValue(DisableINotifyPropertyChangingSupport); - - /// - /// Gets a configuration value for a specified property. - /// - /// The property name to retrieve the value for. - /// The value of the specified configuration setting. - private static bool GetConfigurationValue(string propertyName) - { - if (AppContext.TryGetSwitch(propertyName, out bool isEnabled)) - { - return isEnabled; - } - - return false; - } -} diff --git a/src/CommunityToolkit.Mvvm/Properties/FeatureSwitches.cs b/src/CommunityToolkit.Mvvm/Properties/FeatureSwitches.cs new file mode 100644 index 00000000..13d9ef59 --- /dev/null +++ b/src/CommunityToolkit.Mvvm/Properties/FeatureSwitches.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Runtime.CompilerServices; + +namespace CommunityToolkit.Mvvm; + +/// +/// A container for all shared configuration switches for the MVVM Toolkit. +/// +/// +/// +/// This type uses a very specific setup for configuration switches to ensure ILLink can work the best. +/// This mirrors the architecture of feature switches in the runtime as well, and it's needed so that +/// no static constructor is generated for the type. +/// +/// +/// For more info, see . +/// +/// +internal static class FeatureSwitches +{ + /// + /// The configuration property name for . + /// + private const string EnableINotifyPropertyChangingSupportPropertyName = "MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT"; + + /// + /// The backing field for . + /// + private static int enableINotifyPropertyChangingSupport; + + /// + /// Gets a value indicating whether or not support for should be enabled (defaults to ). + /// + public static bool EnableINotifyPropertyChangingSupport + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => GetConfigurationValue(EnableINotifyPropertyChangingSupportPropertyName, ref enableINotifyPropertyChangingSupport, true); + } + + /// + /// Gets a configuration value for a specified property. + /// + /// The property name to retrieve the value for. + /// The cached result for the target configuration value. + /// The default value for the feature switch, if not set. + /// The value of the specified configuration setting. + private static bool GetConfigurationValue(string propertyName, ref int cachedResult, bool defaultValue) + { + // The cached switch value has 3 states: + // 0: unknown. + // 1: true + // -1: false + // + // This method doesn't need to worry about concurrent accesses to the cached result, + // as even if the configuration value is retrieved twice, that'll always be the same. + if (cachedResult < 0) + { + return false; + } + + if (cachedResult > 0) + { + return true; + } + + // Get the configuration switch value, or its default. + // All feature switches have a default set in the .targets file. + if (!AppContext.TryGetSwitch(propertyName, out bool isEnabled)) + { + isEnabled = defaultValue; + } + + // Update the cached result + cachedResult = isEnabled ? 1 : -1; + + return isEnabled; + } +} \ No newline at end of file From 1e0a83b1b5f5dd3a53f0d9e3f90620581c8f2401 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 17:59:22 -0700 Subject: [PATCH 3/6] Add 'ILLink.Substitutions.xml' file and embed it --- src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj | 5 +++++ .../Properties/ILLink.Substitutions.xml | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/CommunityToolkit.Mvvm/Properties/ILLink.Substitutions.xml diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj index e682aa43..df29a1e9 100644 --- a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.csproj @@ -54,6 +54,11 @@ + + + + + diff --git a/src/CommunityToolkit.Mvvm/Properties/ILLink.Substitutions.xml b/src/CommunityToolkit.Mvvm/Properties/ILLink.Substitutions.xml new file mode 100644 index 00000000..a934a249 --- /dev/null +++ b/src/CommunityToolkit.Mvvm/Properties/ILLink.Substitutions.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file From 395f45ee55a337c5ce9f40c0439026ba9b2383ec Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 18:01:38 -0700 Subject: [PATCH 4/6] Enable feature switch for trimming --- ...ommunityToolkit.Mvvm.FeatureSwitches.targets | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets index 4de98b5c..ea2d3560 100644 --- a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets @@ -1,3 +1,20 @@ + + + true + + + + + + + + + \ No newline at end of file From f3903a1cfe9d780afbfae9466ac8e0cbe49095fb Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 18:48:15 -0700 Subject: [PATCH 5/6] Update 'INotifyPropertyChanging' switch unit test --- dotnet Community Toolkit.sln | 4 ++-- .../Test_DisableINotifyPropertyChanging.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dotnet Community Toolkit.sln b/dotnet Community Toolkit.sln index e8d00435..688e3236 100644 --- a/dotnet Community Toolkit.sln +++ b/dotnet Community Toolkit.sln @@ -53,7 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{CD16E790 build\Update-Headers.ps1 = build\Update-Headers.ps1 EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Configuration", "Configuration", "{6640D447-C28D-4DBB-91F4-3ADCE0CA64AD}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FeatureSwitches", "FeatureSwitches", "{6640D447-C28D-4DBB-91F4-3ADCE0CA64AD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests", "tests\CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests\CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests.csproj", "{9E09DA49-4389-4ECE-8B68-EBDB1221DA90}" EndProject @@ -81,7 +81,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Mvvm.Exter EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Mvvm.ExternalAssembly.Roslyn431", "tests\CommunityToolkit.Mvvm.ExternalAssembly.Roslyn431\CommunityToolkit.Mvvm.ExternalAssembly.Roslyn431.csproj", "{4FCD501C-1BB5-465C-AD19-356DAB6600C6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Mvvm.CodeFixers", "src\CommunityToolkit.Mvvm.CodeFixers\CommunityToolkit.Mvvm.CodeFixers.csproj", "{E79DCA2A-4C59-499F-85BD-F45215ED6B72}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommunityToolkit.Mvvm.CodeFixers", "src\CommunityToolkit.Mvvm.CodeFixers\CommunityToolkit.Mvvm.CodeFixers.csproj", "{E79DCA2A-4C59-499F-85BD-F45215ED6B72}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/Test_DisableINotifyPropertyChanging.cs b/tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/Test_DisableINotifyPropertyChanging.cs index c5fc2c4a..d2a21545 100644 --- a/tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/Test_DisableINotifyPropertyChanging.cs +++ b/tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/Test_DisableINotifyPropertyChanging.cs @@ -14,7 +14,7 @@ public class Test_DisableINotifyPropertyChanging { static Test_DisableINotifyPropertyChanging() { - AppContext.SetSwitch("MVVMTOOLKIT_DISABLE_INOTIFYPROPERTYCHANGING", true); + AppContext.SetSwitch("MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT", false); } [TestMethod] From d8a442f5613a875a0bd96ff7a3effdbe1c2f8f67 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 8 Aug 2024 23:53:02 -0700 Subject: [PATCH 6/6] Streamline bundled .targets across TFMs --- ...munityToolkit.Mvvm.FeatureSwitches.targets | 3 +- .../CommunityToolkit.Mvvm.csproj | 42 ++++--------------- .../CommunityToolkit.Mvvm.targets | 6 +-- 3 files changed, 12 insertions(+), 39 deletions(-) diff --git a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets index ea2d3560..19c3c56c 100644 --- a/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets +++ b/src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets @@ -8,8 +8,9 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - + + + \ No newline at end of file