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