[Perf] Remove the validations in ControllerActivator and ViewComponentActivator which are redundant. These
validations are already done when selecting a controller and view component Fixes #4367
This commit is contained in:
parent
1d4363305c
commit
f4e35f5ba0
|
|
@ -46,16 +46,12 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;
|
var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo;
|
||||||
if (controllerTypeInfo.IsValueType ||
|
|
||||||
controllerTypeInfo.IsInterface ||
|
|
||||||
controllerTypeInfo.IsAbstract ||
|
|
||||||
(controllerTypeInfo.IsGenericType && controllerTypeInfo.IsGenericTypeDefinition))
|
|
||||||
{
|
|
||||||
var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(
|
|
||||||
controllerTypeInfo.FullName,
|
|
||||||
GetType().FullName);
|
|
||||||
|
|
||||||
throw new InvalidOperationException(message);
|
if (controllerTypeInfo == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
|
||||||
|
nameof(controllerContext.ActionDescriptor.ControllerTypeInfo),
|
||||||
|
nameof(ControllerContext.ActionDescriptor)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var serviceProvider = controllerContext.HttpContext.RequestServices;
|
var serviceProvider = controllerContext.HttpContext.RequestServices;
|
||||||
|
|
|
||||||
|
|
@ -45,17 +45,12 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
var componentType = context.ViewComponentDescriptor.TypeInfo;
|
var componentType = context.ViewComponentDescriptor.TypeInfo;
|
||||||
|
|
||||||
if (componentType.IsValueType ||
|
if (componentType == null)
|
||||||
componentType.IsInterface ||
|
|
||||||
componentType.IsAbstract ||
|
|
||||||
(componentType.IsGenericType && componentType.IsGenericTypeDefinition))
|
|
||||||
{
|
{
|
||||||
var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(
|
throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull(
|
||||||
componentType.FullName,
|
nameof(context.ViewComponentDescriptor.TypeInfo),
|
||||||
GetType().FullName);
|
nameof(context.ViewComponentDescriptor)));
|
||||||
|
|
||||||
throw new InvalidOperationException(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewComponent = _typeActivatorCache.CreateInstance<object>(
|
var viewComponent = _typeActivatorCache.CreateInstance<object>(
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,21 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Empty(feature.Controllers);
|
Assert.Empty(feature.Controllers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ValueTypeClass_IsNotController()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controllerType = typeof(int).GetTypeInfo();
|
||||||
|
var manager = GetApplicationPartManager(controllerType);
|
||||||
|
var feature = new ControllerFeature();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
manager.PopulateFeature(feature);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Empty(feature.Controllers);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AbstractClass_IsNotController()
|
public void AbstractClass_IsNotController()
|
||||||
|
|
|
||||||
|
|
@ -58,38 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(true, controller.Disposed);
|
Assert.Equal(true, controller.Disposed);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(typeof(int))]
|
|
||||||
[InlineData(typeof(OpenGenericType<>))]
|
|
||||||
[InlineData(typeof(AbstractType))]
|
|
||||||
[InlineData(typeof(InterfaceType))]
|
|
||||||
public void CreateController_ThrowsIfControllerCannotBeActivated(Type type)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var actionDescriptor = new ControllerActionDescriptor
|
|
||||||
{
|
|
||||||
ControllerTypeInfo = type.GetTypeInfo()
|
|
||||||
};
|
|
||||||
|
|
||||||
var context = new ControllerContext()
|
|
||||||
{
|
|
||||||
ActionDescriptor = actionDescriptor,
|
|
||||||
HttpContext = new DefaultHttpContext()
|
|
||||||
{
|
|
||||||
RequestServices = GetServices(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
var factory = new DefaultControllerActivator(new TypeActivatorCache());
|
|
||||||
|
|
||||||
// Act and Assert
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => factory.Create(context));
|
|
||||||
Assert.Equal(
|
|
||||||
$"The type '{type.FullName}' cannot be activated by '{typeof(DefaultControllerActivator).FullName}' " +
|
|
||||||
"because it is either a value type, an interface, an abstract class or an open generic type.",
|
|
||||||
exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void DefaultControllerActivator_ReleasesNonIDisposableController()
|
public void DefaultControllerActivator_ReleasesNonIDisposableController()
|
||||||
{
|
{
|
||||||
|
|
@ -174,18 +143,6 @@ namespace Microsoft.AspNetCore.Mvc.Controllers
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OpenGenericType<T> : Controller
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class AbstractType : Controller
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface InterfaceType
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MyController : IDisposable
|
private class MyController : IDisposable
|
||||||
{
|
{
|
||||||
public bool Disposed { get; set; }
|
public bool Disposed { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -38,41 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
|
||||||
Assert.Same(context, instance.ViewComponentContext);
|
Assert.Same(context, instance.ViewComponentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(typeof(int))]
|
|
||||||
[InlineData(typeof(OpenGenericType<>))]
|
|
||||||
[InlineData(typeof(AbstractType))]
|
|
||||||
[InlineData(typeof(InterfaceType))]
|
|
||||||
public void Create_ThrowsIfControllerCannotBeActivated(Type type)
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var actionDescriptor = new ViewComponentDescriptor
|
|
||||||
{
|
|
||||||
TypeInfo = type.GetTypeInfo()
|
|
||||||
};
|
|
||||||
|
|
||||||
var context = new ViewComponentContext
|
|
||||||
{
|
|
||||||
ViewComponentDescriptor = actionDescriptor,
|
|
||||||
ViewContext = new ViewContext
|
|
||||||
{
|
|
||||||
HttpContext = new DefaultHttpContext()
|
|
||||||
{
|
|
||||||
RequestServices = Mock.Of<IServiceProvider>()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var activator = new DefaultViewComponentActivator(new TypeActivatorCache());
|
|
||||||
|
|
||||||
// Act and Assert
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(() => activator.Create(context));
|
|
||||||
Assert.Equal(
|
|
||||||
$"The type '{type.FullName}' cannot be activated by '{typeof(DefaultViewComponentActivator).FullName}' " +
|
|
||||||
"because it is either a value type, an interface, an abstract class or an open generic type.",
|
|
||||||
exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void DefaultViewComponentActivator_ActivatesViewComponentContext_IgnoresNonPublic()
|
public void DefaultViewComponentActivator_ActivatesViewComponentContext_IgnoresNonPublic()
|
||||||
{
|
{
|
||||||
|
|
@ -116,18 +81,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OpenGenericType<T> : Controller
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private abstract class AbstractType : Controller
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface InterfaceType
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TestViewComponent : ViewComponent
|
private class TestViewComponent : ViewComponent
|
||||||
{
|
{
|
||||||
public Task ExecuteAsync()
|
public Task ExecuteAsync()
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents
|
||||||
// The Attribute does apply to derived classes.
|
// The Attribute does apply to derived classes.
|
||||||
[InlineData(typeof(WithAttribute), true)]
|
[InlineData(typeof(WithAttribute), true)]
|
||||||
[InlineData(typeof(DerivedWithAttribute), true)]
|
[InlineData(typeof(DerivedWithAttribute), true)]
|
||||||
|
|
||||||
|
// Value types cannot be view components
|
||||||
|
[InlineData(typeof(int), false)]
|
||||||
public void IsComponent(Type type, bool expected)
|
public void IsComponent(Type type, bool expected)
|
||||||
{
|
{
|
||||||
// Arrange & Act
|
// Arrange & Act
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue