Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class DependencyObjectObservableForProperty : ICreatesObservableForProper
{
/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetAffinityForObject uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetAffinityForObject uses methods that may require unreferenced code")]
#endif
public int GetAffinityForObject(Type type, string propertyName, bool beforeChanged = false)
Expand All @@ -41,7 +40,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang

/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetNotificationForProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetNotificationForProperty uses methods that may require unreferenced code")]
#endif
public IObservable<IObservedChange<object, object?>> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false)
Expand Down Expand Up @@ -92,7 +90,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang
}

#if NET6_0_OR_GREATER
[RequiresDynamicCode("ActuallyGetProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ActuallyGetProperty uses methods that may require unreferenced code")]
#endif
private static PropertyInfo? ActuallyGetProperty(TypeInfo typeInfo, string propertyName)
Expand All @@ -113,7 +110,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang
}

#if NET6_0_OR_GREATER
[RequiresDynamicCode("ActuallyGetField uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ActuallyGetField uses methods that may require unreferenced code")]
#endif
private static FieldInfo? ActuallyGetField(TypeInfo typeInfo, string propertyName)
Expand All @@ -134,7 +130,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang
}

#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetDependencyPropertyFetcher uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetDependencyPropertyFetcher uses methods that may require unreferenced code")]
#endif
private static Func<DependencyProperty>? GetDependencyPropertyFetcher(Type type, string propertyName)
Expand Down
1,087 changes: 379 additions & 708 deletions src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet10_0.verified.txt

Large diffs are not rendered by default.

1,087 changes: 379 additions & 708 deletions src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet8_0.verified.txt

Large diffs are not rendered by default.

1,087 changes: 379 additions & 708 deletions src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ public class CreatesWinformsCommandBinding : ICreatesCommandBinding

/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetAffinityForObject uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetAffinityForObject uses methods that may require unreferenced code")]
// [RequiresDynamicCode("GetAffinityForObject uses methods that require dynamic code generation")]
// [RequiresUnreferencedCode("GetAffinityForObject uses methods that may require unreferenced code")]
#endif
public int GetAffinityForObject(Type type, bool hasEventTarget)
public int GetAffinityForObject(
#if NET6_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
Type type,
bool hasEventTarget)
{
var isWinformControl = typeof(Control).IsAssignableFrom(type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace ReactiveUI.Winforms;
/// </summary>
/// <seealso cref="ICreatesObservableForProperty" />
#if NET6_0_OR_GREATER
[RequiresDynamicCode("WinformsCreatesObservableForProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("WinformsCreatesObservableForProperty uses methods that may require unreferenced code")]
#endif
public class WinformsCreatesObservableForProperty : ICreatesObservableForProperty
Expand All @@ -24,7 +23,6 @@ public class WinformsCreatesObservableForProperty : ICreatesObservableForPropert

/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetAffinityForObject uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetAffinityForObject uses methods that may require unreferenced code")]
#endif
public int GetAffinityForObject(Type type, string propertyName, bool beforeChanged = false)
Expand All @@ -41,7 +39,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang

/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetNotificationForProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetNotificationForProperty uses methods that may require unreferenced code")]
#endif
public IObservable<IObservedChange<object, object?>> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false)
Expand Down
9 changes: 0 additions & 9 deletions src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ namespace ReactiveUI;
public class DependencyObjectObservableForProperty : ICreatesObservableForProperty
{
/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetAffinityForObject uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetAffinityForObject uses methods that may require unreferenced code")]
#endif
public int GetAffinityForObject(Type type, string propertyName, bool beforeChanged = false)
{
if (!typeof(DependencyObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()))
Expand All @@ -29,10 +25,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang
}

/// <inheritdoc/>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetNotificationForProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetNotificationForProperty uses methods that may require unreferenced code")]
#endif
public IObservable<IObservedChange<object, object?>> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false)
{
#if NET6_0_OR_GREATER
Expand Down Expand Up @@ -71,7 +63,6 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang
}

#if NET6_0_OR_GREATER
[RequiresDynamicCode("GetDependencyProperty uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("GetDependencyProperty uses methods that may require unreferenced code")]
#endif
private static DependencyProperty? GetDependencyProperty(Type type, string propertyName)
Expand Down
4 changes: 0 additions & 4 deletions src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@

namespace ReactiveUI;

#if NET6_0_OR_GREATER
[RequiresDynamicCode("CreatesCommandBinding uses reflection and generic method instantiation")]
[RequiresUnreferencedCode("CreatesCommandBinding may reference members that could be trimmed")]
#endif
internal static class CreatesCommandBinding
{
private static readonly MemoizingMRUCache<Type, ICreatesCommandBinding?> _bindCommandCache =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ namespace ReactiveUI;
public class CreatesCommandBindingViaCommandParameter : ICreatesCommandBinding
{
/// <inheritdoc/>
public int GetAffinityForObject(
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Property access requires dynamic code generation")]
[RequiresUnreferencedCode("Property access may reference members that could be trimmed")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
public int GetAffinityForObject(Type type, bool hasEventTarget)
Type type,
bool hasEventTarget)
{
if (hasEventTarget)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ public class CreatesCommandBindingViaEvent : ICreatesCommandBinding
];

/// <inheritdoc/>
public int GetAffinityForObject(
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Event binding requires dynamic code generation")]
[RequiresUnreferencedCode("Event binding may reference members that could be trimmed")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
public int GetAffinityForObject(Type type, bool hasEventTarget)
Type type,
bool hasEventTarget)
{
if (hasEventTarget)
{
Expand Down
71 changes: 31 additions & 40 deletions src/ReactiveUI/Expression/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ namespace ReactiveUI;
[Preserve(AllMembers = true)]
public static class Reflection
{
[SuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Marked as Preserve")]
[SuppressMessage("Trimming", "IL2026:Calling members annotated with 'RequiresUnreferencedCodeAttribute' may break functionality when trimming application code.", Justification = "Marked as Preserve")]
private static readonly ExpressionRewriter _expressionRewriter = new();

[SuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Marked as Preserve")]
[SuppressMessage("Trimming", "IL2026:Calling members annotated with 'RequiresUnreferencedCodeAttribute' may break functionality when trimming application code.", Justification = "Marked as Preserve")]
private static readonly MemoizingMRUCache<string, Type?> _typeCache = new(
static (type, _) => GetTypeHelper(type),
Expand All @@ -39,10 +36,6 @@ public static class Reflection
/// </summary>
/// <param name="expression">The expression to generate the property names from.</param>
/// <returns>A string form for the property the expression is pointing to.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Expression tree analysis requires dynamic code generation")]
[RequiresUnreferencedCode("Expression tree analysis may reference members that could be trimmed")]
#endif
public static string ExpressionToPropertyNames(Expression? expression) // TODO: Create Test
{
expression.ArgumentNullExceptionThrowIfNull(nameof(expression));
Expand Down Expand Up @@ -87,10 +80,6 @@ public static string ExpressionToPropertyNames(Expression? expression) // TODO:
/// </summary>
/// <param name="member">The member info to convert.</param>
/// <returns>A Func that takes in the object/indexes and returns the value.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Member access requires dynamic code generation")]
[RequiresUnreferencedCode("Member access may reference members that could be trimmed")]
#endif
public static Func<object?, object?[]?, object?>? GetValueFetcherForProperty(MemberInfo? member) // TODO: Create Test
{
member.ArgumentNullExceptionThrowIfNull(nameof(member));
Expand All @@ -113,10 +102,6 @@ public static string ExpressionToPropertyNames(Expression? expression) // TODO:
/// </summary>
/// <param name="member">The member info to convert.</param>
/// <returns>A Func that takes in the object/indexes and returns the value.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Member access requires dynamic code generation")]
[RequiresUnreferencedCode("Member access may reference members that could be trimmed")]
#endif
public static Func<object?, object?[]?, object?> GetValueFetcherOrThrow(MemberInfo? member) // TODO: Create Test
{
member.ArgumentNullExceptionThrowIfNull(nameof(member));
Expand Down Expand Up @@ -156,10 +141,6 @@ public static string ExpressionToPropertyNames(Expression? expression) // TODO:
/// </summary>
/// <param name="member">The member info to convert.</param>
/// <returns>A Func that takes in the object/indexes and sets the value.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Member access requires dynamic code generation")]
[RequiresUnreferencedCode("Member access may reference members that could be trimmed")]
#endif
public static Action<object?, object?, object?[]?>? GetValueSetterOrThrow(MemberInfo? member) // TODO: Create Test
{
member.ArgumentNullExceptionThrowIfNull(nameof(member));
Expand All @@ -180,10 +161,6 @@ public static string ExpressionToPropertyNames(Expression? expression) // TODO:
/// <param name="expressionChain">A list of expressions which will point towards a property or field.</param>
/// <typeparam name="TValue">The type of the end value we are trying to get.</typeparam>
/// <returns>If the value was successfully retrieved or not.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Expression evaluation requires dynamic code generation")]
[RequiresUnreferencedCode("Expression evaluation may reference members that could be trimmed")]
#endif
public static bool TryGetValueForPropertyChain<TValue>(out TValue changeValue, object? current, IEnumerable<Expression> expressionChain) // TODO: Create Test
{
var expressions = expressionChain.ToList();
Expand Down Expand Up @@ -225,10 +202,6 @@ public static bool TryGetValueForPropertyChain<TValue>(out TValue changeValue, o
/// <param name="current">The object that starts the property chain.</param>
/// <param name="expressionChain">A list of expressions which will point towards a property or field.</param>
/// <returns>If the value was successfully retrieved or not.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Expression evaluation requires dynamic code generation")]
[RequiresUnreferencedCode("Expression evaluation may reference members that could be trimmed")]
#endif
public static bool TryGetAllValuesForPropertyChain(out IObservedChange<object, object?>[] changeValues, object? current, IEnumerable<Expression> expressionChain) // TODO: Create Test
{
var currentIndex = 0;
Expand Down Expand Up @@ -279,10 +252,6 @@ public static bool TryGetAllValuesForPropertyChain(out IObservedChange<object, o
/// <param name="shouldThrow">If we should throw if we are unable to set the value.</param>
/// <typeparam name="TValue">The type of the end value we are trying to set.</typeparam>
/// <returns>If the value was successfully retrieved or not.</returns>
#if NET6_0_OR_GREATER
[RequiresDynamicCode("Expression evaluation requires dynamic code generation")]
[RequiresUnreferencedCode("Expression evaluation may reference members that could be trimmed")]
#endif
public static bool TrySetValueToPropertyChain<TValue>(object? target, IEnumerable<Expression> expressionChain, TValue value, bool shouldThrow = true) // TODO: Create Test
{
var expressions = expressionChain.ToList();
Expand Down Expand Up @@ -345,19 +314,18 @@ public static bool TrySetValueToPropertyChain<TValue>(object? target, IEnumerabl
/// <returns>The Type of the EventArgs to use.</returns>
/// <exception cref="Exception">If there is no event matching the name on the target type.</exception>
#if NET6_0_OR_GREATER
[RequiresUnreferencedCode("Event access may reference members that could be trimmed")]
[RequiresUnreferencedCode("Uses reflection to inspect event handler delegate Invoke method")]
#endif
public static Type GetEventArgsTypeForEvent(
#if NET6_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
#endif
Type type,
string? eventName) // TODO: Create Test
{
type.ArgumentNullExceptionThrowIfNull(nameof(type));

var ti = type;
var ei = ti.GetRuntimeEvent(eventName!);
var ei = type.GetRuntimeEvent(eventName!);
if (ei is null || ei.EventHandlerType is null)
{
throw new Exception($"Couldn't find {type.FullName}.{eventName}");
Expand All @@ -379,11 +347,35 @@ public static Type GetEventArgsTypeForEvent(
[RequiresUnreferencedCode("Method access may reference members that could be trimmed")]
#endif
public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) // TODO: Create Test
{
if (targetObject is null)
{
throw new ArgumentNullException(nameof(targetObject));
}

ThrowIfMethodsNotOverloaded(callingTypeName, targetObject.GetType(), methodsToCheck);
}

/// <summary>
/// Checks to make sure that the specified method names on the target object
/// are overriden.
/// </summary>
/// <param name="callingTypeName">The name of the calling type.</param>
/// <param name="targetType">The type to check.</param>
/// <param name="methodsToCheck">The name of the methods to check.</param>
/// <exception cref="Exception">Thrown if the methods aren't overriden on the target object.</exception>
public static void ThrowIfMethodsNotOverloaded(
string callingTypeName,
#if NET6_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
#endif
Type targetType,
params string[] methodsToCheck) // TODO: Create Test
{
var (methodName, methodImplementation) = methodsToCheck
.Select(x =>
{
var methods = targetObject.GetType().GetTypeInfo().DeclaredMethods;
var methods = targetType.GetTypeInfo().DeclaredMethods;
return (methodName: x, methodImplementation: methods.FirstOrDefault(y => y.Name == x));
})
.FirstOrDefault(x => x.methodImplementation is null);
Expand All @@ -407,9 +399,8 @@ public static bool IsStatic(this PropertyInfo item) // TODO: Create Test
return method.IsStatic;
}

#if NET6_0_OR_GREATER
[RequiresUnreferencedCode("ViewModelWhenAnyValue may reference types that could be trimmed")]
[RequiresDynamicCode("ViewModelWhenAnyValue uses reflection which requires dynamic code generation")]
#if NET6_0_OR_GREATER && WINUI_TARGET
[RequiresUnreferencedCode("The WinUI implementation of ViewModelWhenAnyValue may use methods that require unreferenced code")]
#endif
internal static IObservable<object> ViewModelWhenAnyValue<TView, TViewModel>(TViewModel? viewModel, TView view, Expression? expression)
where TView : class, IViewFor
Expand All @@ -420,7 +411,7 @@ internal static IObservable<object> ViewModelWhenAnyValue<TView, TViewModel>(TVi
.Switch()!;

#if NET6_0_OR_GREATER
[RequiresUnreferencedCode("Method access may reference members that could be trimmed")]
[RequiresUnreferencedCode("The type might be removed")]
#endif
private static Type? GetTypeHelper(string type) => Type.GetType(
type,
Expand Down
7 changes: 4 additions & 3 deletions src/ReactiveUI/Interfaces/ICreatesCommandBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ public interface ICreatesCommandBinding
/// event target.</param>
/// <returns>A positive integer if BCTO is supported, zero or a negative
/// value otherwise.</returns>
int GetAffinityForObject(
#if NET6_0_OR_GREATER
[RequiresDynamicCode("The method uses reflection and will not work in AOT environments.")]
[RequiresUnreferencedCode("The method uses reflection and will not work in AOT environments.")]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
int GetAffinityForObject(Type type, bool hasEventTarget);
Type type,
bool hasEventTarget);

/// <summary>
/// Returns a positive integer when this class supports binding a command
Expand Down
Loading