Make ComponentFactory throw if you try to use [Inject] with a property that has no setter (otherwise it could be confusing)
This commit is contained in:
parent
b4a3c852c5
commit
3f9d358004
|
|
@ -52,16 +52,25 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
// Do all the reflection up front
|
||||
var injectableProperties = type.GetTypeInfo()
|
||||
.GetProperties(_injectablePropertyBindingFlags)
|
||||
.Where(p => p.GetCustomAttribute<InjectAttribute>() != null)
|
||||
.Where(p => p.SetMethod != null);
|
||||
.Where(p => p.GetCustomAttribute<InjectAttribute>() != null);
|
||||
var injectables = injectableProperties.Select(property =>
|
||||
(
|
||||
propertyName: property.Name,
|
||||
propertyType: property.PropertyType,
|
||||
setter: (IPropertySetter)Activator.CreateInstance(
|
||||
typeof(PropertySetter<,>).MakeGenericType(type, property.PropertyType),
|
||||
property.SetMethod)
|
||||
)).ToArray();
|
||||
{
|
||||
if (property.SetMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot provide a value for property " +
|
||||
$"'{property.Name}' on type '{type.FullName}' because the property " +
|
||||
$"has no setter.");
|
||||
}
|
||||
|
||||
return
|
||||
(
|
||||
propertyName: property.Name,
|
||||
propertyType: property.PropertyType,
|
||||
setter: (IPropertySetter)Activator.CreateInstance(
|
||||
typeof(PropertySetter<,>).MakeGenericType(type, property.PropertyType),
|
||||
property.SetMethod)
|
||||
);
|
||||
}).ToArray();
|
||||
|
||||
// Return an action whose closure can write all the injected properties
|
||||
// without any further reflection calls (just typecasts)
|
||||
|
|
@ -72,7 +81,7 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
|||
var serviceInstance = _serviceProvider.GetService(injectable.propertyType);
|
||||
if (serviceInstance == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot provide value for property " +
|
||||
throw new InvalidOperationException($"Cannot provide a value for property " +
|
||||
$"'{injectable.propertyName}' on type '{type.FullName}'. There is no " +
|
||||
$"registered service of type '{injectable.propertyType}'.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,13 +42,16 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void IgnoresGetOnlyProperties()
|
||||
public void ThrowsForInjectablePropertiesWithoutSetter()
|
||||
{
|
||||
// Arrange/Act
|
||||
var component = InstantiateComponent<HasGetOnlyProperty>();
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
InstantiateComponent<HasGetOnlyPropertyWithInject>();
|
||||
});
|
||||
|
||||
// Assert
|
||||
Assert.Null(component.MyService);
|
||||
Assert.Equal($"Cannot provide a value for property '{nameof(HasInjectableProperty.MyService)}' " +
|
||||
$"on type '{typeof(HasGetOnlyPropertyWithInject).FullName}' because the property " +
|
||||
$"has no setter.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -59,7 +62,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
InstantiateComponent<HasInjectableProperty>();
|
||||
});
|
||||
|
||||
Assert.Equal($"Cannot provide value for property '{nameof(HasInjectableProperty.MyService)}' " +
|
||||
Assert.Equal($"Cannot provide a value for property '{nameof(HasInjectableProperty.MyService)}' " +
|
||||
$"on type '{typeof(HasInjectableProperty).FullName}'. There is no registered service " +
|
||||
$"of type '{typeof(IMyService).FullName}'.", ex.Message);
|
||||
}
|
||||
|
|
@ -130,7 +133,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
|||
public static IMyService StaticPropertyWithoutInject { get; set; }
|
||||
}
|
||||
|
||||
class HasGetOnlyProperty : TestComponent
|
||||
class HasGetOnlyPropertyWithInject : TestComponent
|
||||
{
|
||||
[Inject] public IMyService MyService { get; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue