diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/BindableTypeProviders/BindableTypeProvidersGenerationTask.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/BindableTypeProviders/BindableTypeProvidersGenerationTask.cs index 51ad7abef74f..12986efd5d3a 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/BindableTypeProviders/BindableTypeProvidersGenerationTask.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/BindableTypeProviders/BindableTypeProvidersGenerationTask.cs @@ -302,6 +302,7 @@ where field.IsStatic writer.AppendLineIndented("[global::System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1502:AvoidExcessiveComplexity\", Justification=\"Must be ignored even if generated code is checked.\")]"); writer.AppendLineIndented("[global::System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1506:AvoidExcessiveClassCoupling\", Justification = \"Must be ignored even if generated code is checked.\")]"); writer.AppendLineIndented("[global::System.Diagnostics.CodeAnalysis.SuppressMessage(\"Microsoft.Maintainability\", \"CA1505:AvoidUnmaintainableCode\", Justification = \"Must be ignored even if generated code is checked.\")]"); + writer.AppendLineIndented("[global::System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage(\"Trimming\", \"IL2111\", Justification = \"`typeof(Type)` emits IL2111 because of `Type.TypeInitializer`, which is not used.\")]"); using (writer.BlockInvariant("internal static global::Uno.UI.DataBinding.IBindableType Build(global::Uno.UI.DataBinding.BindableType parent)")) { RegisterHintMethod($"MetadataBuilder_{typeInfo.Index:000}", ownerType, "Uno.UI.DataBinding.IBindableType Build(Uno.UI.DataBinding.BindableType)"); diff --git a/src/Uno.UI/DataBinding/BindableProperty.cs b/src/Uno.UI/DataBinding/BindableProperty.cs index 852e7ec0a8b7..373079d0f8f9 100644 --- a/src/Uno.UI/DataBinding/BindableProperty.cs +++ b/src/Uno.UI/DataBinding/BindableProperty.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -24,7 +25,11 @@ public BindableProperty(DependencyProperty property) /// /// This ctor is available for backward compatibility. On newer versions of Uno.UI, the BindableTypeProvidersSourceGenerator uses the single-parameter ctor /// - public BindableProperty(Type propertyType, PropertyGetterHandler getter, PropertySetterHandler? setter) + public BindableProperty( + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] + Type propertyType, + PropertyGetterHandler getter, + PropertySetterHandler? setter) { Getter = getter; Setter = setter; @@ -35,6 +40,7 @@ public BindableProperty(Type propertyType, PropertyGetterHandler getter, Propert public PropertySetterHandler? Setter { get; } + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] public Type PropertyType { get; } public DependencyProperty? DependencyProperty { get; } diff --git a/src/Uno.UI/DataBinding/BindableType.cs b/src/Uno.UI/DataBinding/BindableType.cs index e5f362d4fdc7..635d94bfd4ca 100644 --- a/src/Uno.UI/DataBinding/BindableType.cs +++ b/src/Uno.UI/DataBinding/BindableType.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -16,6 +17,13 @@ namespace Uno.UI.DataBinding /// public class BindableType : IBindableType { + internal const DynamicallyAccessedMemberTypes TypeRequirements = + DynamicallyAccessedMemberTypes.NonPublicConstructors // DependencyProperty.Register() + | DynamicallyAccessedMemberTypes.PublicConstructors + | DynamicallyAccessedMemberTypes.PublicFields + | DynamicallyAccessedMemberTypes.PublicProperties + ; + private readonly Hashtable _properties; private StringIndexerGetterDelegate? _stringIndexerGetter; private StringIndexerSetterDelegate? _stringIndexerSetter; @@ -26,12 +34,16 @@ public class BindableType : IBindableType /// /// Provide an estimated number of properties, so the dictionary does not need to grow unnecessarily. /// The actual .NET type that corresponds to this instance. - public BindableType(int estimatedPropertySize, Type sourceType) + public BindableType( + int estimatedPropertySize, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] + Type sourceType) { _properties = new Hashtable(estimatedPropertySize); Type = sourceType; } + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] public Type Type { get; } public ActivatorDelegate? CreateInstance() @@ -61,7 +73,9 @@ public void AddActivator(ActivatorDelegate activator) _activator = activator; } - public void AddProperty(string name, PropertyGetterHandler getter, PropertySetterHandler? setter = null) + public void AddProperty< + [DynamicallyAccessedMembers(TypeRequirements)] T + >(string name, PropertyGetterHandler getter, PropertySetterHandler? setter = null) { _properties[name] = new BindableProperty(typeof(T), getter, setter); } @@ -71,7 +85,12 @@ public void AddProperty(DependencyProperty property) _properties[property.Name] = new BindableProperty(property); } - public void AddProperty(string name, Type propertyType, PropertyGetterHandler getter, PropertySetterHandler? setter = null) + public void AddProperty( + string name, + [DynamicallyAccessedMembers(TypeRequirements)] + Type propertyType, + PropertyGetterHandler getter, + PropertySetterHandler? setter = null) { _properties[name] = new BindableProperty(propertyType, getter, setter); } diff --git a/src/Uno.UI/DataBinding/IBindableProperty.cs b/src/Uno.UI/DataBinding/IBindableProperty.cs index e5c730e1752e..4172052a0292 100644 --- a/src/Uno.UI/DataBinding/IBindableProperty.cs +++ b/src/Uno.UI/DataBinding/IBindableProperty.cs @@ -3,6 +3,7 @@ using Microsoft.UI.Xaml; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; @@ -26,6 +27,7 @@ public interface IBindableProperty /// /// Gets the type of the property /// + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type PropertyType { get; } /// diff --git a/src/Uno.UI/DataBinding/IBindableType.cs b/src/Uno.UI/DataBinding/IBindableType.cs index 5cb44c7b8788..0c6e07ee837e 100644 --- a/src/Uno.UI/DataBinding/IBindableType.cs +++ b/src/Uno.UI/DataBinding/IBindableType.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -31,6 +32,7 @@ public interface IBindableType /// /// Provides the Type of this bindable type /// + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type Type { get; } /// diff --git a/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.Properties.cs b/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.Properties.cs index a918ed8d6e72..9797c4d97c92 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.Properties.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Frame/Frame.Properties.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Microsoft.UI.Xaml.Navigation; namespace Microsoft.UI.Xaml.Controls; @@ -117,6 +118,8 @@ public Type CurrentSourcePageType /// /// Identifies the CurrentSourcePageType dependency property. /// + [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "`typeof(Type)` triggers IL2111 regarding `Type.TypeInitializer`, but Uno doesn't use `Type.TypeInitializer`!")] + // warning IL2111: Method 'System.Type.TypeInitializer.get' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. public static DependencyProperty CurrentSourcePageTypeProperty { get; } = DependencyProperty.Register( nameof(CurrentSourcePageType), @@ -174,6 +177,8 @@ public Type SourcePageType /// /// Identifies the SourcePageType dependency property. /// + [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "`typeof(Type)` triggers IL2111 regarding `Type.TypeInitializer`, but Uno doesn't use `Type.TypeInitializer`!")] + // warning IL2111: Method 'System.Type.TypeInitializer.get' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. public static DependencyProperty SourcePageTypeProperty { get; } = DependencyProperty.Register( nameof(SourcePageType), diff --git a/src/Uno.UI/UI/Xaml/DependencyProperty.cs b/src/Uno.UI/UI/Xaml/DependencyProperty.cs index ae69c2f44178..7fef939347b1 100644 --- a/src/Uno.UI/UI/Xaml/DependencyProperty.cs +++ b/src/Uno.UI/UI/Xaml/DependencyProperty.cs @@ -16,6 +16,7 @@ using Uno; using Uno.Extensions; using Uno.UI; +using Uno.UI.DataBinding; using Uno.UI.Dispatching; using Uno.UI.Helpers; using Uno.UI.Xaml.Media; @@ -54,13 +55,22 @@ public sealed partial class DependencyProperty private readonly Flags _flags; private string _name; + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] private Type _propertyType; + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] private Type _ownerType; private readonly int _uniqueId; private static int _globalId = -1; - private DependencyProperty(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, bool attached) + private DependencyProperty( + string name, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] + Type propertyType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] + Type ownerType, + PropertyMetadata defaultMetadata, + bool attached) { _name = name; _propertyType = propertyType; @@ -140,8 +150,8 @@ internal bool IsDependencyObjectCollection /// A property with the same name has already been declared for the ownerType public static DependencyProperty Register( string name, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type propertyType, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type ownerType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type propertyType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type ownerType, PropertyMetadata typeMetadata) { typeMetadata = FixMetadataIfNeeded(propertyType, typeMetadata); @@ -196,8 +206,8 @@ private static PropertyMetadata FixMetadataIfNeeded( /// internal static DependencyProperty Register( string name, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type propertyType, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type ownerType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type propertyType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type ownerType, FrameworkPropertyMetadata typeMetadata) #pragma warning disable RS0030 // Do not used banned APIs => Register(name, propertyType, ownerType, (PropertyMetadata)typeMetadata); @@ -214,8 +224,8 @@ internal static DependencyProperty Register( /// A property with the same name has already been declared for the ownerType public static DependencyProperty RegisterAttached( string name, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type propertyType, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type ownerType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type propertyType, + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] Type ownerType, PropertyMetadata defaultMetadata) { defaultMetadata = FixMetadataIfNeeded(propertyType, defaultMetadata); @@ -297,11 +307,13 @@ public PropertyMetadata GetMetadata(Type forType) return _ownerTypeMetadata.CloneWithOverwrittenDefaultValue(defaultValueForType); } + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] internal Type OwnerType { get { return _ownerType; } } + [DynamicallyAccessedMembers(BindableType.TypeRequirements)] internal Type Type { get { return _propertyType; } diff --git a/src/Uno.UI/UI/Xaml/Navigation/PageStackEntry.Properties.cs b/src/Uno.UI/UI/Xaml/Navigation/PageStackEntry.Properties.cs index 5a300df148b7..65c61bb48cb7 100644 --- a/src/Uno.UI/UI/Xaml/Navigation/PageStackEntry.Properties.cs +++ b/src/Uno.UI/UI/Xaml/Navigation/PageStackEntry.Properties.cs @@ -37,7 +37,8 @@ public Type SourcePageType /// /// Identifies the SourcePageType dependency property. /// - [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "@jonpryor has no idea what the trimmer is talking about.")] + [UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "`typeof(Type)` triggers IL2111 regarding `Type.TypeInitializer`, but Uno doesn't use `Type.TypeInitializer`!")] + // warning IL2111: Method 'System.Type.TypeInitializer.get' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method. public static DependencyProperty SourcePageTypeProperty { get; } = DependencyProperty.Register( nameof(SourcePageType),