From 84be0b11691d319a17458d95f5773b5002979f49 Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Thu, 23 Jan 2025 00:16:48 +0000 Subject: [PATCH] Remove BinaryFormatter, Start Adding AOT Markup (#3943) **What kind of change does this PR introduce?** update **What is the current behavior?** BinaryFormatter is used for suspension **What is the new behavior?** Remove BinaryFormatter Start adding AOT Markup **What might this PR break?** Suspension will fail to Deserialize **** BREAKING CHANGE **** **Please check if the PR fulfills these requirements** - [ ] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) **Other information**: --- ...valTests.ReactiveUI.DotNet8_0.verified.txt | 18 +++++++++++++++++- ...valTests.ReactiveUI.DotNet9_0.verified.txt | 18 +++++++++++++++++- ...provalTests.ReactiveUI.Net4_7.verified.txt | 2 +- .../Bindings/Command/CreatesCommandBinding.cs | 4 ++++ ...reatesCommandBindingViaCommandParameter.cs | 8 ++++++++ .../Command/CreatesCommandBindingViaEvent.cs | 12 ++++++++++++ src/ReactiveUI/Expression/Reflection.cs | 8 ++++++++ .../Interfaces/ISuspensionDriver.cs | 4 ++-- src/ReactiveUI/Mixins/AutoPersistHelper.cs | 2 +- src/ReactiveUI/PlatformRegistrationManager.cs | 6 +++++- .../android/BundleSuspensionDriver.cs | 18 ++++++++++++------ .../Platforms/android/ReactiveViewHost.cs | 8 ++++++++ .../AppSupportJsonSuspensionDriver.cs | 19 ++++++++++++------- .../ComponentModelTypeConverter.cs | 2 +- src/ReactiveUI/ReactiveUI.csproj | 8 ++++++-- src/ReactiveUI/View/DefaultViewLocator.cs | 7 +++++++ 16 files changed, 121 insertions(+), 23 deletions(-) diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt index bb602deeb..81f67c638 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt @@ -117,15 +117,25 @@ namespace ReactiveUI public class CreatesCommandBindingViaCommandParameter : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaCommandParameter() { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter) { } public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter, string eventName) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class CreatesCommandBindingViaEvent : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaEvent() { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter, string eventName) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class DecimalToStringTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger @@ -137,6 +147,8 @@ namespace ReactiveUI public sealed class DefaultViewLocator : ReactiveUI.IViewLocator, Splat.IEnableLogger { public System.Func ViewModelToViewFunc { get; set; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The method is used to resolve views for view models.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public ReactiveUI.IViewFor? ResolveView(T? viewModel, string? contract = null) { } } public static class DependencyResolverMixins @@ -369,7 +381,7 @@ namespace ReactiveUI public interface ISuspensionDriver { System.IObservable InvalidateState(); - System.IObservable LoadState(); + System.IObservable LoadState(); System.IObservable SaveState(object state); } public interface ISuspensionHost : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging @@ -813,6 +825,8 @@ namespace ReactiveUI public static class Reflection { public static string ExpressionToPropertyNames(System.Linq.Expressions.Expression? expression) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeMethods()")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeMethods()")] public static System.Type GetEventArgsTypeForEvent(System.Type type, string? eventName) { } public static System.Func? GetValueFetcherForProperty(System.Reflection.MemberInfo? member) { } public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo? member) { } @@ -821,6 +835,8 @@ namespace ReactiveUI public static bool IsStatic(this System.Reflection.PropertyInfo item) { } public static System.Type? ReallyFindType(string? type, bool throwOnFailure) { } public static System.Linq.Expressions.Expression Rewrite(System.Linq.Expressions.Expression? expression) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetTypeInfo()")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetTypeInfo()")] public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) { } public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange[] changeValues, object? current, System.Collections.Generic.IEnumerable expressionChain) { } public static bool TryGetValueForPropertyChain(out TValue changeValue, object? current, System.Collections.Generic.IEnumerable expressionChain) { } diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt index e9c2561cf..40452cf55 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt @@ -117,15 +117,25 @@ namespace ReactiveUI public class CreatesCommandBindingViaCommandParameter : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaCommandParameter() { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter) { } public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter, string eventName) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class CreatesCommandBindingViaEvent : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaEvent() { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand? command, object? target, System.IObservable commandParameter, string eventName) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class DecimalToStringTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger @@ -137,6 +147,8 @@ namespace ReactiveUI public sealed class DefaultViewLocator : ReactiveUI.IViewLocator, Splat.IEnableLogger { public System.Func ViewModelToViewFunc { get; set; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The method is used to resolve views for view models.")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] public ReactiveUI.IViewFor? ResolveView(T? viewModel, string? contract = null) { } } public static class DependencyResolverMixins @@ -369,7 +381,7 @@ namespace ReactiveUI public interface ISuspensionDriver { System.IObservable InvalidateState(); - System.IObservable LoadState(); + System.IObservable LoadState(); System.IObservable SaveState(object state); } public interface ISuspensionHost : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging @@ -813,6 +825,8 @@ namespace ReactiveUI public static class Reflection { public static string ExpressionToPropertyNames(System.Linq.Expressions.Expression? expression) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetRuntimeMethods()")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetRuntimeMethods()")] public static System.Type GetEventArgsTypeForEvent(System.Type type, string? eventName) { } public static System.Func? GetValueFetcherForProperty(System.Reflection.MemberInfo? member) { } public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo? member) { } @@ -821,6 +835,8 @@ namespace ReactiveUI public static bool IsStatic(this System.Reflection.PropertyInfo item) { } public static System.Type? ReallyFindType(string? type, bool throwOnFailure) { } public static System.Linq.Expressions.Expression Rewrite(System.Linq.Expressions.Expression? expression) { } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls GetTypeInfo()")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls GetTypeInfo()")] public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) { } public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange[] changeValues, object? current, System.Collections.Generic.IEnumerable expressionChain) { } public static bool TryGetValueForPropertyChain(out TValue changeValue, object? current, System.Collections.Generic.IEnumerable expressionChain) { } diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt index 781f7821c..901c49b22 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.Net4_7.verified.txt @@ -367,7 +367,7 @@ namespace ReactiveUI public interface ISuspensionDriver { System.IObservable InvalidateState(); - System.IObservable LoadState(); + System.IObservable LoadState(); System.IObservable SaveState(object state); } public interface ISuspensionHost : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs index 2a7d32471..047fc2deb 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs @@ -40,6 +40,10 @@ public static IDisposable BindCommandToObject(ICommand? command, object? target, return ret; } +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] +#endif public static IDisposable BindCommandToObject(ICommand? command, object? target, IObservable commandParameter, string? eventName) { var type = target!.GetType(); diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs index 591c73569..9df238561 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs @@ -14,6 +14,10 @@ namespace ReactiveUI; public class CreatesCommandBindingViaCommandParameter : ICreatesCommandBinding { /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] + [RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] +#endif public int GetAffinityForObject(Type type, bool hasEventTarget) { if (hasEventTarget) @@ -35,6 +39,10 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls GetRuntimeProperty(string name)")] + [RequiresDynamicCode("Calls GetRuntimeProperty(string name)")] +#endif public IDisposable? BindCommandToObject(ICommand? command, object? target, IObservable commandParameter) { target.ArgumentNullExceptionThrowIfNull(nameof(target)); diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs index 82ce0ac38..7b201069d 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs @@ -30,6 +30,10 @@ public class CreatesCommandBindingViaEvent : ICreatesCommandBinding ]; /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] +#endif public int GetAffinityForObject(Type type, bool hasEventTarget) { if (hasEventTarget) @@ -45,6 +49,10 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] +#endif public IDisposable? BindCommandToObject(ICommand? command, object? target, IObservable commandParameter) { target.ArgumentNullExceptionThrowIfNull(nameof(target)); @@ -61,6 +69,10 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [RequiresDynamicCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] +#endif public IDisposable? BindCommandToObject(ICommand? command, object? target, IObservable commandParameter, string eventName) #if MONO where TEventArgs : EventArgs diff --git a/src/ReactiveUI/Expression/Reflection.cs b/src/ReactiveUI/Expression/Reflection.cs index 4f308d956..476bec9ec 100644 --- a/src/ReactiveUI/Expression/Reflection.cs +++ b/src/ReactiveUI/Expression/Reflection.cs @@ -331,6 +331,10 @@ public static bool TrySetValueToPropertyChain(object? target, IEnumerabl /// The name of the event. /// The Type of the EventArgs to use. /// If there is no event matching the name on the target type. +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls GetRuntimeMethods()")] + [RequiresDynamicCode("Calls GetRuntimeMethods()")] +#endif public static Type GetEventArgsTypeForEvent(Type type, string? eventName) // TODO: Create Test { type.ArgumentNullExceptionThrowIfNull(nameof(type)); @@ -354,6 +358,10 @@ public static Type GetEventArgsTypeForEvent(Type type, string? eventName) // TOD /// The object to check. /// The name of the methods to check. /// Thrown if the methods aren't overriden on the target object. +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls GetTypeInfo()")] + [RequiresDynamicCode("Calls GetTypeInfo()")] +#endif public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) // TODO: Create Test { var (methodName, methodImplementation) = methodsToCheck diff --git a/src/ReactiveUI/Interfaces/ISuspensionDriver.cs b/src/ReactiveUI/Interfaces/ISuspensionDriver.cs index 76a211eba..1e0163a83 100644 --- a/src/ReactiveUI/Interfaces/ISuspensionDriver.cs +++ b/src/ReactiveUI/Interfaces/ISuspensionDriver.cs @@ -16,7 +16,7 @@ public interface ISuspensionDriver /// Loads the application state from persistent storage. /// /// An object observable. - IObservable LoadState(); + IObservable LoadState(); /// /// Saves the application state to disk. @@ -30,4 +30,4 @@ public interface ISuspensionDriver /// /// A completed observable. IObservable InvalidateState(); -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Mixins/AutoPersistHelper.cs b/src/ReactiveUI/Mixins/AutoPersistHelper.cs index 53f1ef2f1..cb66425cd 100644 --- a/src/ReactiveUI/Mixins/AutoPersistHelper.cs +++ b/src/ReactiveUI/Mixins/AutoPersistHelper.cs @@ -17,7 +17,7 @@ namespace ReactiveUI; public static class AutoPersistHelper { private static readonly MemoizingMRUCache> _persistablePropertiesCache = new( - (type, _) => type.GetTypeInfo().DeclaredProperties + static (type, _) => type.GetTypeInfo().DeclaredProperties .Where(x => x.CustomAttributes.Any(y => typeof(DataMemberAttribute).GetTypeInfo().IsAssignableFrom(y.AttributeType.GetTypeInfo()))) .ToDictionary(k => k.Name, _ => true), RxApp.SmallCacheLimit); diff --git a/src/ReactiveUI/PlatformRegistrationManager.cs b/src/ReactiveUI/PlatformRegistrationManager.cs index c5a4045b0..44fb8e7a3 100644 --- a/src/ReactiveUI/PlatformRegistrationManager.cs +++ b/src/ReactiveUI/PlatformRegistrationManager.cs @@ -11,7 +11,11 @@ namespace ReactiveUI; public static class PlatformRegistrationManager { internal static RegistrationNamespace[] DefaultRegistrationNamespaces { get; } = +#if NET6_0_OR_GREATER + Enum.GetValues(); +#else (RegistrationNamespace[])Enum.GetValues(typeof(RegistrationNamespace)); +#endif internal static RegistrationNamespace[] NamespacesToRegister { get; set; } = DefaultRegistrationNamespaces; @@ -21,4 +25,4 @@ public static class PlatformRegistrationManager /// /// The namespaces to register. public static void SetRegistrationNamespaces(params RegistrationNamespace[] namespaces) => NamespacesToRegister = namespaces; -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs b/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs index 0b421bc09..96e62dca1 100644 --- a/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs +++ b/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs @@ -4,7 +4,7 @@ // See the LICENSE file in the project root for full license information. using System.IO; -using System.Runtime.Serialization.Formatters.Binary; +using System.Text.Json; namespace ReactiveUI; @@ -14,7 +14,11 @@ namespace ReactiveUI; public class BundleSuspensionDriver : ISuspensionDriver { /// - public IObservable LoadState() // TODO: Create Test +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls Deserialize()")] + [RequiresDynamicCode("Calls Deserialize()")] +#endif + public IObservable LoadState() // TODO: Create Test { try { @@ -24,7 +28,6 @@ public IObservable LoadState() // TODO: Create Test return Observable.Throw(new Exception("New bundle, start from scratch")); } - var serializer = new BinaryFormatter(); var buffer = AutoSuspendHelper.LatestBundle.GetByteArray("__state"); if (buffer is null) @@ -34,7 +37,7 @@ public IObservable LoadState() // TODO: Create Test var st = new MemoryStream(buffer); - return Observable.Return(serializer.Deserialize(st)); + return Observable.Return(JsonSerializer.Deserialize(st)); } catch (Exception ex) { @@ -43,13 +46,16 @@ public IObservable LoadState() // TODO: Create Test } /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls Serialize()")] + [RequiresDynamicCode("Calls Serialize()")] +#endif public IObservable SaveState(object state) // TODO: Create Test { try { - var serializer = new BinaryFormatter(); var st = new MemoryStream(); - + JsonSerializer.Serialize(st, state); AutoSuspendHelper.LatestBundle?.PutByteArray("__state", st.ToArray()); return Observables.Unit; } diff --git a/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs index cbba39ee6..b02eba04f 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs @@ -36,6 +36,8 @@ public abstract class ReactiveViewHost : LayoutViewHost, IViewForThe parent. /// if set to true [attach to root]. /// if set to true [perform automatic wire-up]. + [RequiresUnreferencedCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] + [RequiresDynamicCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] protected ReactiveViewHost(Context ctx, int layoutId, ViewGroup parent, bool attachToRoot = false, bool performAutoWireup = true) : base(ctx, layoutId, parent, attachToRoot, performAutoWireup) => SetupRxObj(); @@ -43,6 +45,8 @@ protected ReactiveViewHost(Context ctx, int layoutId, ViewGroup parent, bool att /// /// Initializes a new instance of the class. /// + [RequiresUnreferencedCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] + [RequiresDynamicCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] protected ReactiveViewHost() => SetupRxObj(); /// @@ -104,8 +108,12 @@ public TViewModel? ViewModel void IReactiveObject.RaisePropertyChanged(PropertyChangedEventArgs args) => PropertyChanged?.Invoke(this, args); [OnDeserialized] + [RequiresUnreferencedCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] + [RequiresDynamicCode("Calls ReactiveUI.ReactiveViewHost.SetupRxObj()")] private void SetupRxObj(in StreamingContext sc) => SetupRxObj(); + [RequiresUnreferencedCode("Calls GetProperties(BindingFlags bindingAttr)")] + [RequiresDynamicCode("Calls GetProperties(BindingFlags bindingAttr)")] private void SetupRxObj() => allPublicProperties = new Lazy(() => [.. GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)]); diff --git a/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs b/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs index fe75dd94a..d15d3673c 100644 --- a/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs +++ b/src/ReactiveUI/Platforms/apple-common/AppSupportJsonSuspensionDriver.cs @@ -4,8 +4,7 @@ // See the LICENSE file in the project root for full license information. using System.IO; -using System.Runtime.Serialization.Formatters.Binary; - +using System.Text.Json; using Foundation; namespace ReactiveUI; @@ -16,17 +15,20 @@ namespace ReactiveUI; public class AppSupportJsonSuspensionDriver : ISuspensionDriver { /// - public IObservable LoadState() +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls Deserialize()")] + [RequiresDynamicCode("Calls Deserialize()")] +#endif + public IObservable LoadState() { try { - var serializer = new BinaryFormatter(); var target = Path.Combine(CreateAppDirectory(NSSearchPathDirectory.ApplicationSupportDirectory), "state.dat"); var result = default(object); using (var st = File.OpenRead(target)) { - result = serializer.Deserialize(st); + result = JsonSerializer.Deserialize(st); } return Observable.Return(result); @@ -38,16 +40,19 @@ public IObservable LoadState() } /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls Serialize()")] + [RequiresDynamicCode("Calls Serialize()")] +#endif public IObservable SaveState(object state) { try { - var serializer = new BinaryFormatter(); var target = Path.Combine(CreateAppDirectory(NSSearchPathDirectory.ApplicationSupportDirectory), "state.dat"); using (var st = File.Open(target, FileMode.Create)) { - serializer.Serialize(st, state); + JsonSerializer.Serialize(st, state); } return Observables.Unit; diff --git a/src/ReactiveUI/Platforms/mobile-common/ComponentModelTypeConverter.cs b/src/ReactiveUI/Platforms/mobile-common/ComponentModelTypeConverter.cs index 61435e140..54fe4ab2c 100644 --- a/src/ReactiveUI/Platforms/mobile-common/ComponentModelTypeConverter.cs +++ b/src/ReactiveUI/Platforms/mobile-common/ComponentModelTypeConverter.cs @@ -11,7 +11,7 @@ namespace ReactiveUI; public class ComponentModelTypeConverter : IBindingTypeConverter { private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?> _typeConverterCache = new( - (types, _) => + static (types, _) => { // NB: String is a Magical Type(tm) to TypeConverters. If we are // converting from string => int, we need the Int converter, not diff --git a/src/ReactiveUI/ReactiveUI.csproj b/src/ReactiveUI/ReactiveUI.csproj index 09799c69b..581126c91 100644 --- a/src/ReactiveUI/ReactiveUI.csproj +++ b/src/ReactiveUI/ReactiveUI.csproj @@ -6,8 +6,8 @@ ReactiveUI A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. This is the base package with the base platform implementations ReactiveUI - - $(NoWarn);SYSLIB0011;IDE1006 + 14.2 14.0 21.0 @@ -15,6 +15,10 @@ 10.0.17763.0 6.5 + + true + + diff --git a/src/ReactiveUI/View/DefaultViewLocator.cs b/src/ReactiveUI/View/DefaultViewLocator.cs index 3289cd89c..743da7f40 100644 --- a/src/ReactiveUI/View/DefaultViewLocator.cs +++ b/src/ReactiveUI/View/DefaultViewLocator.cs @@ -87,6 +87,10 @@ internal DefaultViewLocator(Func? viewModelToViewFunc = null) => /// /// The view associated with the given view model. /// +#if NET6_0_OR_GREATER + [RequiresUnreferencedCode("Calls System.Reflection.MethodInfo.MakeGenericMethod(params Type[])")] + [RequiresDynamicCode("The method is used to resolve views for view models.")] +#endif public IViewFor? ResolveView(T? viewModel, string? contract = null) { viewModel.ArgumentNullExceptionThrowIfNull(nameof(viewModel)); @@ -171,6 +175,9 @@ private static string InterfaceifyTypeName(string typeName) return typeName.Insert(idxPeriod + 1, "I"); } +#if NET6_0_OR_GREATER + [RequiresDynamicCode("The method is used to resolve views for view models.")] +#endif private IViewFor? AttemptViewResolutionFor(Type? viewModelType, string? contract) { if (viewModelType is null)