Skip to content

Commit c153534

Browse files
authored
Support NativeAOT in PropertySetter (#49897)
* Support NativeAOT in PropertySetter MakeGenericType and MakeGeneridMethod aren't guaranteed to work on NativeAOT when using value types. When dynamic code isn't supported, just use normal reflection to set the property instead of creating generic delegates. * Add test to ensure PropertySetter works when IsDynamicCodeSupported == false.
1 parent 31ec16d commit c153534

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

src/Components/Components/src/Reflection/PropertySetter.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Diagnostics.CodeAnalysis;
55
using System.Reflection;
6+
using System.Runtime.CompilerServices;
67

78
namespace Microsoft.AspNetCore.Components.Reflection;
89

@@ -26,14 +27,21 @@ public PropertySetter(Type targetType, PropertyInfo property)
2627
"has no setter.");
2728
}
2829

29-
var setMethod = property.SetMethod;
30+
if (RuntimeFeature.IsDynamicCodeSupported)
31+
{
32+
var setMethod = property.SetMethod;
3033

31-
var propertySetterAsAction =
32-
setMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(targetType, property.PropertyType));
33-
var callPropertySetterClosedGenericMethod =
34-
CallPropertySetterOpenGenericMethod.MakeGenericMethod(targetType, property.PropertyType);
35-
_setterDelegate = (Action<object, object>)
36-
callPropertySetterClosedGenericMethod.CreateDelegate(typeof(Action<object, object>), propertySetterAsAction);
34+
var propertySetterAsAction =
35+
setMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(targetType, property.PropertyType));
36+
var callPropertySetterClosedGenericMethod =
37+
CallPropertySetterOpenGenericMethod.MakeGenericMethod(targetType, property.PropertyType);
38+
_setterDelegate = (Action<object, object>)
39+
callPropertySetterClosedGenericMethod.CreateDelegate(typeof(Action<object, object>), propertySetterAsAction);
40+
}
41+
else
42+
{
43+
_setterDelegate = property.SetValue;
44+
}
3745
}
3846

3947
public bool AcceptsDirectParameters { get; init; }

src/Components/Components/test/ParameterViewTest.Assignment.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System.Collections;
55
using Microsoft.AspNetCore.Components.Rendering;
6+
using Microsoft.AspNetCore.Testing;
7+
using Microsoft.DotNet.RemoteExecutor;
68

79
namespace Microsoft.AspNetCore.Components;
810

@@ -598,6 +600,32 @@ public void SupplyingNullWritesDefaultForType()
598600
Assert.Null(target.StringProp);
599601
}
600602

603+
[ConditionalFact]
604+
[RemoteExecutionSupported]
605+
public void WorksWhenDynamicCodeNotSupported()
606+
{
607+
var options = new RemoteInvokeOptions();
608+
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false");
609+
610+
using var remoteHandle = RemoteExecutor.Invoke(static () =>
611+
{
612+
// Arrange
613+
var parameters = new ParameterViewBuilder
614+
{
615+
{ nameof(HasInstanceProperties.IntProp), 5 },
616+
{ nameof(HasInstanceProperties.StringProp), "Hello" },
617+
}.Build();
618+
var target = new HasInstanceProperties();
619+
620+
// Act
621+
parameters.SetParameterProperties(target);
622+
623+
// Assert
624+
Assert.Equal(5, target.IntProp);
625+
Assert.Equal("Hello", target.StringProp);
626+
}, options);
627+
}
628+
601629
class HasInstanceProperties
602630
{
603631
[Parameter] public int IntProp { get; set; }

0 commit comments

Comments
 (0)