Skip to content

Commit e4157bf

Browse files
committed
chore: Preserve ModelAttribute.Bindable constructors, properties
Context: unoplatform/uno.chefs#1709 While running the uno.chefs app on macOS under NativeAOT: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop -bl \ Chefs/Chefs.csproj \ -p:SelfContained=true -p:PublishAot=true -p:IsAotCompatible=true -p:UseSkiaRendering=true \ -p:IlcGenerateMapFile=true -p:IlcGenerateMstatFile=true -p:IlcGenerateDgmlFile=true \ -p:EmitCompilerGeneratedFiles=true -p:CompilerGeneratedFilesOutputPath=`pwd`/_gen Chefs/bin/Release/net10.0-desktop/osx-x64/publish/Chefs (along with a change from unoplatform/uno.chefs#1709 to `Program.cs` to call `App.InitializeLogging()`…) Console output would contain the following warnings: fail: Uno.UI.Dispatching.NativeDispatcher[0] NativeDispatcher unhandled exception System.InvalidOperationException: A suitable constructor for type 'Chefs.Presentation.ShellViewModel' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor. This is actually fixable within uno.extensions! The `ShellViewModel` type is referenced by *both* `[Model]` and `IModel<ShelViewModel>` in generated code: // Chefs.Presentation.ShellModel.g.cs namespace Chefs.Presentation; [Model(typeof(ShellViewModel))] partial record ShellModel : IModel<ShellViewModel> { } `ModelAttribute` and `IModel<TViewModel>` thus give us places to tell NativeAOT to preserve the constructors on `ShellViewModel`. After having done so, the new failure message appears: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [Pages] property getter does not exist on type [Chefs.Presentation.WelcomeViewModel] This can *also* be fixed by telling NativeAOT to preserve *properties* as well, as `WelcomeViewModel` goes through similar infrastructure as `ShellViewModel`. Update `ModelAttribute` so that the `Type bindable` constructor parameter preserves both constructors and properties. Update `IModel<TViewModel>` *for consistency* with `[Model]` to also preserve constructor and properties on type parameter `TViewModel`. TODO: this fixes `ShellViewModel` and similar constructs, but next we have: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [CurrentIndex] property getter does not exist on type [Chefs.Business.Models.BindableIntIteratorViewModel] There are no `[Model]` or `IModel<TViewModel>` uses which mention `BindableIntIteratorViewModel`, so the current fix doesn't help. Investigate what needs to be done to fix `BindableIntIteratorViewModel`.
1 parent 2af4d6b commit e4157bf

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

src/Uno.Extensions.Reactive/Presentation/Bindings/IModel.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.ComponentModel;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45

56
namespace Uno.Extensions.Reactive.Bindings;
@@ -13,7 +14,9 @@ namespace Uno.Extensions.Reactive.Bindings;
1314
/// EVen if it's not recommended, this gives to the _Model_ to ability to interact with its _ViewModel_ if needed.
1415
/// </remarks>
1516
[EditorBrowsable(EditorBrowsableState.Advanced)]
16-
public interface IModel<out TViewModel>
17+
public interface IModel<
18+
[DynamicallyAccessedMembers(ModelAttribute.BindableRequirements)]
19+
out TViewModel>
1720
{
1821
/// <summary>
1922
/// Gets the instance of the view model associated to this model.

src/Uno.Extensions.Reactive/Presentation/Bindings/ModelAttribute.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.ComponentModel;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45

56
namespace Uno.Extensions.Reactive.Bindings;
@@ -12,16 +13,24 @@ namespace Uno.Extensions.Reactive.Bindings;
1213
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
1314
public class ModelAttribute : Attribute
1415
{
16+
internal const DynamicallyAccessedMemberTypes BindableRequirements =
17+
DynamicallyAccessedMemberTypes.PublicConstructors
18+
| DynamicallyAccessedMemberTypes.PublicProperties
19+
;
20+
1521
/// <summary>
1622
/// Type of the generated bindable for the _model_.
1723
/// </summary>
24+
[DynamicallyAccessedMembers(BindableRequirements)]
1825
public Type Bindable { get; }
1926

2027
/// <summary>
2128
/// Flags a class as a _model_.
2229
/// </summary>
2330
/// <param name="bindable">The type of the _bindable view model_.</param>
24-
public ModelAttribute(Type bindable)
31+
public ModelAttribute(
32+
[DynamicallyAccessedMembers(BindableRequirements)]
33+
Type bindable)
2534
{
2635
Bindable = bindable;
2736
}

0 commit comments

Comments
 (0)