* Mark relevant assemblies as AOT compatible

* Fix straightforward trimming warnings

* Simplify ValueConverterExtension.IsValidTargetType

* Update ValueConverterExtension.shared.cs

* Add `<IsAotCompatible>true</IsAotCompatible>` to `CommunityToolkit.Maui.Camera`

* Add AOT WarningsAsErrors

* Promote Trimmer + AOT Warnings to Errors

* Fix missing comma

* Publish Sample app using AOT

* Resolve Trim Warnings

* `dotnet format`

* Remove AOT from Tizen sample

* Replace `Enum.GetValues(Type)` with `EnumGetValues<T>()`

* Remove 'android-arm' and 'android-x86'

* Fix AOT on Windows

* Remove Android AOT

* Set `win-x64` runtime for default Release builds

* Fix naming

* Update CommunityToolkit.Maui.Sample.csproj

---------

Co-authored-by: Brandon Minnick <13558917+brminnick@users.noreply.github.com>
This commit is contained in:
Šimon Rozsíval 2024-09-07 22:02:08 +02:00 коммит произвёл GitHub
Родитель c28eefa0cc
Коммит 725dd4153b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
23 изменённых файлов: 136 добавлений и 43 удалений

Просмотреть файл

@ -12,7 +12,10 @@
<GenerateErrorForMissingTargetingPacks>false</GenerateErrorForMissingTargetingPacks>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<IsTrimmable>false</IsTrimmable>
<!-- https://learn.microsoft.com/dotnet/core/deploying/native-aot/?tabs=net8plus%2Cwindows -->
<StripSymbols>false</StripSymbols>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
<!-- WarningsAsErrors
CS0419: Ambiguous reference in cref attribute
@ -37,8 +40,27 @@
CS1723: XML comment has cref attribute that refers to a type parameter
CS1734: XML comment has a paramref tag, but there is no parameter by that name
xUnit1012: Null should not be used for type parameter
xUnit2021: Assert.ThrowsAsync is async. The resulting task should be awaited -->
<WarningsAsErrors>nullable,CS0419,CS1570,CS1571,CS1572,CS1573,CS1574,CS1580,CS1581,CS1584,CS1587,CS1589,CS1590,CS1591,CS1592,CS1598,CS1658,CS1710,CS1711,CS1712,CS1723,CS1734,xUnit1012,xUnit2021</WarningsAsErrors>
xUnit2021: Assert.ThrowsAsync is async. The resulting task should be awaited
IL2***: Trim Warnings
IL3***: AOT Warnings -->
<WarningsAsErrors>nullable,
CS0419,CS1570,CS1571,CS1572,CS1573,CS1574,CS1580,CS1581,CS1584,CS1587,CS1589,CS1590,CS1591,CS1592,CS1598,CS1658,CS1710,CS1711,CS1712,CS1723,CS1734,
xUnit1012,xUnit2021,
IL2001,IL2002,IL2003,IL2004,IL2005,IL2006,IL2007,IL2008,IL2009,
IL2010,IL2011,IL2012,IL2013,IL2014,IL2015,IL2016,IL2017,IL2018,IL2019,
IL2020,IL2021,IL2022,IL2023,IL2024,IL2025,IL2026,IL2027,IL2028,IL2029,
IL2030,IL2031,IL2032,IL2033,IL2034,IL2035,IL2036,IL2037,IL2038,IL2039,
IL2040,IL2041,IL2042,IL2043,IL2044,IL2045,IL2046,IL2047,IL2048,IL2049,
IL2050,IL2051,IL2052,IL2053,IL2054,IL2055,IL2056,IL2057,IL2058,IL2059,
IL2060,IL2061,IL2062,IL2063,IL2064,IL2065,IL2066,IL2067,IL2068,IL2069,
IL2070,IL2071,IL2072,IL2073,IL2074,IL2075,IL2076,IL2077,IL2078,IL2079,
IL2080,IL2081,IL2082,IL2083,IL2084,IL2085,IL2086,IL2087,IL2088,IL2089,
IL2090,IL2091,IL2092,IL2093,IL2094,IL2095,IL2096,IL2097,IL2098,IL2099,
IL2100,IL2101,IL2102,IL2103,IL2104,IL2105,IL2106,IL2107,IL2108,IL2109,
IL2110,IL2111,IL2112,IL2113,IL2114,IL2115,IL2116,IL2117,IL2118,IL2119,
IL2120,IL2121,IL2122,
IL3050,IL3051,IL3052,IL3053,IL3054,IL3055,IL3056
</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>

Просмотреть файл

@ -33,6 +33,16 @@
<!--<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>-->
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'
AND $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'tizen'
AND $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'android'
AND $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'windows'">
<!-- Ahead-of-time compilation is not yet supported net8.0-tizen -->
<!-- Cross-OS native compilation is not supported net8.0-android -->
<!-- Only iOS + MacCatalyst support AOT in .NET 8 -->
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
@ -77,6 +87,10 @@
<ProjectReference Include="..\..\src\CommunityToolkit.Maui.Maps\CommunityToolkit.Maui.Maps.csproj" />
</ItemGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))=='windows' and $(Configuration) == 'Release'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))=='android'">
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<RuntimeIdentifiers>android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>

Просмотреть файл

@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using CommunityToolkit.Maui.ApplicationModel;
using CommunityToolkit.Maui.Maps;
using CommunityToolkit.Maui.Markup;
@ -266,7 +267,7 @@ public static class MauiProgram
services.AddSingleton<ITextToSpeech>(TextToSpeech.Default);
}
static IServiceCollection AddTransientWithShellRoute<TPage, TViewModel>(this IServiceCollection services) where TPage : BasePage<TViewModel>
static IServiceCollection AddTransientWithShellRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPage, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services) where TPage : BasePage<TViewModel>
where TViewModel : BaseViewModel
{
return services.AddTransientWithShellRoute<TPage, TViewModel>(AppShell.GetPageRoute<TViewModel>());

Просмотреть файл

@ -4,5 +4,5 @@ namespace CommunityToolkit.Maui.Sample.ViewModels.Behaviors;
public class CharactersValidationBehaviorViewModel : BaseViewModel
{
public IReadOnlyList<CharacterType> CharacterTypes { get; } = Enum.GetValues(typeof(CharacterType)).Cast<CharacterType>().ToList();
public IReadOnlyList<CharacterType> CharacterTypes { get; } = [.. Enum.GetValues<CharacterType>()];
}

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>

Просмотреть файл

@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;
using Microsoft.Maui.Controls.Maps;
using Microsoft.Maui.Handlers;
@ -40,8 +41,15 @@ public partial class MapHandlerWindows : MapHandler
}
/// <inheritdoc/>
[RequiresDynamicCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
#if NET8_0 // Should be fixed in .NET 9
#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
protected override FrameworkElement CreatePlatformView()
#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
#endif
{
if (string.IsNullOrEmpty(MapsKey))
{
@ -57,7 +65,15 @@ public partial class MapHandlerWindows : MapHandler
}
/// <inheritdoc />
[RequiresDynamicCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
#if NET8_0 // Should be fixed in .NET 9
#pragma warning disable IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
#pragma warning disable IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
protected override void DisconnectHandler(FrameworkElement platformView)
#pragma warning restore IL3051 // 'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.
#pragma warning restore IL2046 // 'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.
#endif
{
if (PlatformView is MauiWebView mauiWebView)
{
@ -396,6 +412,8 @@ public partial class MapHandlerWindows : MapHandler
}
}
[RequiresDynamicCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
[RequiresUnreferencedCode("Calls System.Text.Json.JsonSerializer.Deserialize<TValue>(String, JsonSerializerOptions)")]
void WebViewWebMessageReceived(WebView2 sender, CoreWebView2WebMessageReceivedEventArgs args)
{
// For some reason the web message is empty

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>

Просмотреть файл

@ -11,8 +11,8 @@ public partial class MediaElementHandler : ViewHandler<MediaElement, MauiMediaEl
/// <see cref="MediaElement"/> and platform counterpart.
/// </summary>
/// <param name="handler">The associated handler.</param>
/// <param name="MediaElement">The associated <see cref="MediaElement"/> instance.</param>
public static void ShouldLoopPlayback(MediaElementHandler handler, MediaElement MediaElement)
/// <param name="mediaElement">The associated <see cref="MediaElement"/> instance.</param>
public static void ShouldLoopPlayback(MediaElementHandler handler, MediaElement mediaElement)
{
handler.mediaManager?.UpdateShouldLoopPlayback();
}

Просмотреть файл

@ -394,7 +394,7 @@ public partial class MediaManager : IDisposable
return res;
}
foreach (AppFW.ResourceManager.Category category in Enum.GetValues(typeof(AppFW.ResourceManager.Category)))
foreach (AppFW.ResourceManager.Category category in Enum.GetValues<AppFW.ResourceManager.Category>())
{
var path = AppFW.ResourceManager.TryGetPath(category, res);

Просмотреть файл

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace CommunityToolkit.Maui.Behaviors;
@ -59,6 +60,7 @@ public abstract class BaseBehavior<TView> : Behavior<TView>, ICommunityToolkitBe
/// <returns></returns>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete($"{nameof(IsBound)} is no longer used by {nameof(CommunityToolkit)}.{nameof(CommunityToolkit.Maui)} and will be removed in a future release")]
[RequiresUnreferencedCode($"The {nameof(IsBound)} method is not trim compatible")]
protected bool IsBound(BindableProperty property, BindingBase? defaultBinding = null)
{
var getContextMethod = typeof(BindableObject).GetRuntimeMethods().FirstOrDefault(m => m.Name is "GetContext");

Просмотреть файл

@ -6,6 +6,7 @@
<TargetFrameworks Condition="'$(IncludeTizenTargetFrameworks)' == 'true'">$(TargetFrameworks);$(NetVersion)-tizen</TargetFrameworks>
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>

Просмотреть файл

@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using CommunityToolkit.Maui.Extensions;
@ -10,7 +11,7 @@ namespace CommunityToolkit.Maui.Converters;
/// <typeparam name="TFrom">Type of the input value.</typeparam>
/// <typeparam name="TTo">Type of the output value.</typeparam>
/// <typeparam name="TParam">Type of parameter</typeparam>
public abstract class BaseConverter<TFrom, TTo, TParam> : ValueConverterExtension, ICommunityToolkitValueConverter
public abstract class BaseConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFrom, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTo, TParam> : ValueConverterExtension, ICommunityToolkitValueConverter
{
/// <summary>
/// Default value to return when <see cref="IValueConverter.Convert(object?, Type, object?, CultureInfo?)"/> throws an <see cref="Exception"/>.
@ -25,9 +26,11 @@ public abstract class BaseConverter<TFrom, TTo, TParam> : ValueConverterExtensio
public abstract TFrom DefaultConvertBackReturnValue { get; set; }
/// <inheritdoc/>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
public Type FromType { get; } = typeof(TFrom);
/// <inheritdoc/>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
public Type ToType { get; } = typeof(TTo);
/// <summary>
@ -57,7 +60,7 @@ public abstract class BaseConverter<TFrom, TTo, TParam> : ValueConverterExtensio
public abstract TFrom ConvertBackTo(TTo value, TParam parameter, CultureInfo? culture);
/// <inheritdoc/>
object? ICommunityToolkitValueConverter.ConvertBack(object? value, Type targetType, object? parameter, CultureInfo? culture)
object? ICommunityToolkitValueConverter.ConvertBack(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture)
{
try
{
@ -76,7 +79,7 @@ public abstract class BaseConverter<TFrom, TTo, TParam> : ValueConverterExtensio
}
/// <inheritdoc/>
object? ICommunityToolkitValueConverter.Convert(object? value, Type targetType, object? parameter, CultureInfo? culture)
object? ICommunityToolkitValueConverter.Convert(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture)
{
try
{
@ -100,7 +103,7 @@ public abstract class BaseConverter<TFrom, TTo, TParam> : ValueConverterExtensio
/// </summary>
/// <typeparam name="TFrom">Type of the input value.</typeparam>
/// <typeparam name="TTo">Type of the output value.</typeparam>
public abstract class BaseConverter<TFrom, TTo> : ValueConverterExtension, ICommunityToolkitValueConverter
public abstract class BaseConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFrom, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTo> : ValueConverterExtension, ICommunityToolkitValueConverter
{
/// <summary>
/// Default value to return when <see cref="IValueConverter.Convert(object?, Type, object?, CultureInfo?)"/> throws an <see cref="Exception"/>.
@ -115,9 +118,11 @@ public abstract class BaseConverter<TFrom, TTo> : ValueConverterExtension, IComm
public abstract TFrom DefaultConvertBackReturnValue { get; set; }
/// <inheritdoc/>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
public Type FromType { get; } = typeof(TFrom);
/// <inheritdoc/>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
public Type ToType { get; } = typeof(TTo);
object? ICommunityToolkitValueConverter.DefaultConvertReturnValue => DefaultConvertReturnValue;
@ -140,7 +145,7 @@ public abstract class BaseConverter<TFrom, TTo> : ValueConverterExtension, IComm
public abstract TFrom ConvertBackTo(TTo value, CultureInfo? culture);
/// <inheritdoc/>
object? ICommunityToolkitValueConverter.ConvertBack(object? value, Type targetType, object? parameter, CultureInfo? culture)
object? ICommunityToolkitValueConverter.ConvertBack(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture)
{
try
{
@ -158,7 +163,7 @@ public abstract class BaseConverter<TFrom, TTo> : ValueConverterExtension, IComm
}
/// <inheritdoc/>
object? ICommunityToolkitValueConverter.Convert(object? value, Type targetType, object? parameter, CultureInfo? culture)
object? ICommunityToolkitValueConverter.Convert(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture)
{
try
{

Просмотреть файл

@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace CommunityToolkit.Maui.Converters;
@ -7,7 +8,7 @@ namespace CommunityToolkit.Maui.Converters;
/// </summary>
/// <typeparam name="TFrom">Type of the input value</typeparam>
/// <typeparam name="TTo">Type of the output value</typeparam>
public abstract class BaseConverterOneWay<TFrom, TTo> : BaseConverter<TFrom, TTo>
public abstract class BaseConverterOneWay<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFrom, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTo> : BaseConverter<TFrom, TTo>
{
/// <inheritdoc/>
public sealed override TFrom DefaultConvertBackReturnValue
@ -27,7 +28,7 @@ public abstract class BaseConverterOneWay<TFrom, TTo> : BaseConverter<TFrom, TTo
/// <typeparam name="TFrom">Type of the input value</typeparam>
/// <typeparam name="TTo">Type of the output value</typeparam>
/// <typeparam name="TParam">Type of parameter</typeparam>
public abstract class BaseConverterOneWay<TFrom, TTo, TParam> : BaseConverter<TFrom, TTo, TParam>
public abstract class BaseConverterOneWay<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFrom, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTo, TParam> : BaseConverter<TFrom, TTo, TParam>
{
/// <inheritdoc/>
public sealed override TFrom DefaultConvertBackReturnValue

Просмотреть файл

@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace CommunityToolkit.Maui.Converters;
@ -12,7 +13,7 @@ public class BoolToObjectConverter : BoolToObjectConverter<object>
/// <summary>
/// Converts <see cref="bool"/> to object and vice versa.
/// </summary>
public class BoolToObjectConverter<TObject> : BaseConverter<bool, TObject?>
public class BoolToObjectConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TObject> : BaseConverter<bool, TObject?>
{
/// <inheritdoc/>
public override TObject? DefaultConvertReturnValue { get; set; } = default;

Просмотреть файл

@ -14,7 +14,7 @@ public sealed class CompareConverter : CompareConverter<IComparable, object>
/// <summary>
/// Converts an object that implements IComparable to an object or a boolean based on a comparison.
/// </summary>
public abstract class CompareConverter<TValue, TReturnObject> : BaseConverterOneWay<TValue, object> where TValue : IComparable
public abstract class CompareConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TValue, TReturnObject> : BaseConverterOneWay<TValue, object> where TValue : IComparable
{
/// <inheritdoc/>
public override object DefaultConvertReturnValue { get; set; } = new();

Просмотреть файл

@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace CommunityToolkit.Maui.Converters;
@ -20,11 +21,13 @@ public interface ICommunityToolkitValueConverter : IValueConverter
/// <summary>
/// Gets the <see cref="Type" /> this converter expects to <see cref="Convert" /> from or <see cref="ConvertBack" /> to.
/// </summary>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type FromType { get; }
/// <summary>
/// Gets the <see cref="Type" /> this converter expects to <see cref="Convert" /> to or <see cref="ConvertBack" /> from.
/// </summary>
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type ToType { get; }
/// <summary>
@ -35,7 +38,7 @@ public interface ICommunityToolkitValueConverter : IValueConverter
/// <param name="parameter">Optional Parameters</param>
/// <param name="culture">Culture Info</param>
/// <returns>The converted object</returns>
new object? Convert(object? value, Type targetType, object? parameter, CultureInfo? culture);
new object? Convert(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture);
/// <summary>
/// Converts the object back to the outgoing values
@ -45,13 +48,20 @@ public interface ICommunityToolkitValueConverter : IValueConverter
/// <param name="parameter">Optional Parameters</param>
/// <param name="culture">Culture Info</param>
/// <returns>The object converted back</returns>
new object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo? culture);
new object? ConvertBack(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo? culture);
/// <inheritdoc />
object? IValueConverter.Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
#if NET8_0 // Should be fixed in .NET 9
#pragma warning disable IL2092
#endif
object? IValueConverter.Convert(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo culture) =>
Convert(value, targetType, parameter, culture);
/// <inheritdoc />
object? IValueConverter.ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) =>
object? IValueConverter.ConvertBack(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, CultureInfo culture) =>
ConvertBack(value, targetType, parameter, culture);
#if NET8_0
#pragma warning restore IL2092
#endif
}

Просмотреть файл

@ -1,4 +1,5 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace CommunityToolkit.Maui.Converters;
@ -6,7 +7,7 @@ namespace CommunityToolkit.Maui.Converters;
public sealed class IsInRangeConverter : IsInRangeConverter<IComparable, object>;
/// <summary>Converts the incoming value to a <see cref="bool"/> indicating whether or not the value is within a range.</summary>
public abstract class IsInRangeConverter<TValue, TReturnObject> : BaseConverterOneWay<TValue, object> where TValue : IComparable
public abstract class IsInRangeConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TValue, TReturnObject> : BaseConverterOneWay<TValue, object> where TValue : IComparable
{
/// <summary>
/// Bindable property for <see cref="FalseObject"/>

Просмотреть файл

@ -1,4 +1,6 @@
namespace CommunityToolkit.Maui.Converters;
using System.Diagnostics.CodeAnalysis;
namespace CommunityToolkit.Maui.Converters;
/// <summary>
/// Converts an incoming value using all of the incoming converters in sequence.
@ -9,10 +11,15 @@ public class MultiConverter : List<ICommunityToolkitValueConverter>, ICommunityT
object? ICommunityToolkitValueConverter.DefaultConvertBackReturnValue => throw new NotSupportedException($"{nameof(ICommunityToolkitMultiValueConverter)} does not implement {nameof(ICommunityToolkitValueConverter.DefaultConvertBackReturnValue)}");
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type ICommunityToolkitValueConverter.FromType => throw new NotSupportedException($"{nameof(ICommunityToolkitMultiValueConverter)} does not implement {nameof(ICommunityToolkitValueConverter.FromType)}");
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type ICommunityToolkitValueConverter.ToType => throw new NotSupportedException($"{nameof(ICommunityToolkitMultiValueConverter)} does not implement {nameof(ICommunityToolkitValueConverter.ToType)}");
#if NET8_0 // Should be fixed in .NET 9
#pragma warning disable IL2092
#endif
/// <summary>
/// Uses the incoming converters to convert the value.
/// </summary>
@ -21,7 +28,7 @@ public class MultiConverter : List<ICommunityToolkitValueConverter>, ICommunityT
/// <param name="parameter">Parameter to pass into subsequent converters.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>The converted value.</returns>
public object? Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo? culture)
public object? Convert(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, System.Globalization.CultureInfo? culture)
=> parameter is IList<MultiConverterParameter> parameters
? this.Aggregate(value, (current, converter) => converter.Convert(current, converter.ToType,
parameters.FirstOrDefault(x => x.ConverterType == converter.GetType())?.Value, culture))
@ -35,6 +42,9 @@ public class MultiConverter : List<ICommunityToolkitValueConverter>, ICommunityT
/// <param name="parameter">N/A</param>
/// <param name="culture">N/A</param>
/// <returns>N/A</returns>
public object? ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo? culture)
public object? ConvertBack(object? value, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, object? parameter, System.Globalization.CultureInfo? culture)
=> throw new NotSupportedException("Impossible to revert to original value. Consider setting BindingMode to OneWay.");
#if NET8_0 // Should be fixed in .NET 9
#pragma warning restore IL2092
#endif
}

Просмотреть файл

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using CommunityToolkit.Maui.Views;
// Using root CommunityToolkit.Maui namespace so these extension methods
@ -24,7 +25,7 @@ public static class ServiceCollectionExtensions
/// <remarks>Developers are still responsible for assigning the injected instance of
/// <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddTransient<TView, TViewModel>(this IServiceCollection services)
public static IServiceCollection AddTransient<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services)
where TView : BindableObject
where TViewModel : class, INotifyPropertyChanged
{
@ -43,7 +44,7 @@ public static class ServiceCollectionExtensions
/// <see cref="INotifyPropertyChanged"/></typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
/// <returns>A reference to this instance after the operation has completed.</returns>
public static IServiceCollection AddTransientPopup<TPopupView, TPopupViewModel>(this IServiceCollection services)
public static IServiceCollection AddTransientPopup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPopupView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPopupViewModel>(this IServiceCollection services)
where TPopupView : Popup
where TPopupViewModel : INotifyPropertyChanged
{
@ -69,7 +70,7 @@ public static class ServiceCollectionExtensions
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <remarks>Developers are still responsible for assigning the injected instance of <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddTransientWithShellRoute<TView, TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
public static IServiceCollection AddTransientWithShellRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
where TView : NavigableElement
where TViewModel : class, INotifyPropertyChanged
{
@ -89,7 +90,7 @@ public static class ServiceCollectionExtensions
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <remarks>Developers are still responsible for assigning the injected instance of <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddSingleton<TView, TViewModel>(this IServiceCollection services)
public static IServiceCollection AddSingleton<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services)
where TView : BindableObject
where TViewModel : class, INotifyPropertyChanged
{
@ -115,7 +116,7 @@ public static class ServiceCollectionExtensions
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <remarks>Developers are still responsible for assigning the injected instance of <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddSingletonWithShellRoute<TView, TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
public static IServiceCollection AddSingletonWithShellRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
where TView : NavigableElement
where TViewModel : class, INotifyPropertyChanged
{
@ -135,7 +136,7 @@ public static class ServiceCollectionExtensions
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <remarks>Developers are still responsible for assigning the injected instance of <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddScoped<TView, TViewModel>(this IServiceCollection services)
public static IServiceCollection AddScoped<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services)
where TView : BindableObject
where TViewModel : class, INotifyPropertyChanged
{
@ -161,7 +162,7 @@ public static class ServiceCollectionExtensions
/// <returns>A reference to this instance after the operation has completed.</returns>
/// <remarks>Developers are still responsible for assigning the injected instance of <typeparamref name="TViewModel" />
/// to the BindingContext property of <typeparamref name="TView" />.</remarks>
public static IServiceCollection AddScopedWithShellRoute<TView, TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
public static IServiceCollection AddScopedWithShellRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TViewModel>(this IServiceCollection services, string route, RouteFactory? factory = null)
where TView : NavigableElement
where TViewModel : class, INotifyPropertyChanged
{
@ -176,7 +177,7 @@ public static class ServiceCollectionExtensions
/// <param name="route">Route at which this page will be registered within Shell routing.</param>
/// <param name="factory">RouteFactory to be used while creating the <see cref="NavigableElement"/>
/// for the route. Defaults to TypeRouteFactory.</param>
static void RegisterShellRoute<TView>(string route, RouteFactory? factory = null)
static void RegisterShellRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TView>(string route, RouteFactory? factory = null)
where TView : NavigableElement
{
if (factory is null)

Просмотреть файл

@ -1,4 +1,5 @@
using CommunityToolkit.Maui.Converters;
using System.Diagnostics.CodeAnalysis;
using CommunityToolkit.Maui.Converters;
namespace CommunityToolkit.Maui.Extensions;
@ -11,7 +12,7 @@ public abstract class ValueConverterExtension : BindableObject, IMarkupExtension
private protected static bool IsNullable<T>() => IsNullable(typeof(T));
private protected static bool IsValidTargetType<TTarget>(in Type targetType, bool shouldAllowNullableValueTypes)
private protected static bool IsValidTargetType<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTarget>([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] in Type targetType, bool shouldAllowNullableValueTypes)
{
if (IsConvertingToString(targetType) && CanBeConvertedToString())
{
@ -54,7 +55,7 @@ public abstract class ValueConverterExtension : BindableObject, IMarkupExtension
}
}
private protected static void ValidateTargetType<TTarget>(Type targetType, bool shouldAllowNullableValueTypes)
private protected static void ValidateTargetType<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TTarget>([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type targetType, bool shouldAllowNullableValueTypes)
{
ArgumentNullException.ThrowIfNull(targetType);

Просмотреть файл

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Views;
using Microsoft.Maui.Controls.Platform;
@ -35,7 +36,7 @@ public class PopupService : IPopupService
?? throw new InvalidOperationException("Could not locate IServiceProvider");
}
internal static void AddTransientPopup<TPopupView, TPopupViewModel>(IServiceCollection services)
internal static void AddTransientPopup<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPopupView, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TPopupViewModel>(IServiceCollection services)
where TPopupView : IPopup
where TPopupViewModel : INotifyPropertyChanged
{