Issue #39 move init code into controller factory

This commit is contained in:
Ryan Nowak 2014-03-06 12:44:36 -08:00
parent 9d0cea17dd
commit 318c19b2f9
3 changed files with 43 additions and 50 deletions

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.Abstractions; using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.DependencyInjection; using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
@ -14,26 +16,20 @@ namespace Microsoft.AspNet.Mvc
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
} }
public object CreateController(HttpContext context, ActionDescriptor actionDescriptor) public object CreateController(ActionContext actionContext, ModelStateDictionary modelState)
{ {
var typedAd = actionDescriptor as ReflectedActionDescriptor; var actionDescriptor = actionContext.ActionDescriptor as ReflectedActionDescriptor;
if (actionDescriptor == null)
if (typedAd == null)
{ {
return null; return null;
} }
try try
{ {
var controller = ActivatorUtilities.CreateInstance(_serviceProvider, typedAd.ControllerDescriptor.ControllerTypeInfo.AsType()); var controller = ActivatorUtilities.CreateInstance(_serviceProvider, actionDescriptor.ControllerDescriptor.ControllerTypeInfo.AsType());
// TODO: How do we feed the controller with context (need DI improvements) // TODO: How do we feed the controller with context (need DI improvements)
var contextProperty = controller.GetType().GetRuntimeProperty("Context"); InitializeController(controller, actionContext, modelState);
if (contextProperty != null)
{
contextProperty.SetMethod.Invoke(controller, new object[] { context });
}
return controller; return controller;
} }
@ -47,5 +43,35 @@ namespace Microsoft.AspNet.Mvc
public void ReleaseController(object controller) public void ReleaseController(object controller)
{ {
} }
private void InitializeController(object controller, ActionContext actionContext, ModelStateDictionary modelState)
{
var controllerType = controller.GetType();
foreach (var prop in controllerType.GetRuntimeProperties())
{
if (prop.Name == "Context" && prop.PropertyType == typeof(HttpContext))
{
prop.SetValue(controller, actionContext.HttpContext);
}
else if (prop.Name == "ModelState" && prop.PropertyType == typeof(ModelStateDictionary))
{
prop.SetValue(controller, modelState);
}
}
var method = controllerType.GetRuntimeMethods().FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
if (method == null)
{
return;
}
var args = method.GetParameters()
.Select(p => _serviceProvider.GetService(p.ParameterType)).ToArray();
method.Invoke(controller, args);
}
} }
} }

View File

@ -1,10 +1,11 @@
using Microsoft.AspNet.Abstractions; 
using Microsoft.AspNet.Mvc.ModelBinding;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public interface IControllerFactory public interface IControllerFactory
{ {
object CreateController(HttpContext context, ActionDescriptor actionDescriptor); object CreateController(ActionContext actionContext, ModelStateDictionary modelState);
void ReleaseController(object controller); void ReleaseController(object controller);
} }

View File

@ -35,9 +35,10 @@ namespace Microsoft.AspNet.Mvc
public async Task InvokeActionAsync() public async Task InvokeActionAsync()
{ {
IActionResult actionResult = null; IActionResult actionResult;
object controller = _controllerFactory.CreateController(_actionContext.HttpContext, _descriptor); var modelState = new ModelStateDictionary();
object controller = _controllerFactory.CreateController(_actionContext, modelState);
if (controller == null) if (controller == null)
{ {
@ -45,9 +46,6 @@ namespace Microsoft.AspNet.Mvc
} }
else else
{ {
var modelState = new ModelStateDictionary();
InitializeController(controller, modelState);
var method = _descriptor.MethodInfo; var method = _descriptor.MethodInfo;
if (method == null) if (method == null)
@ -68,38 +66,6 @@ namespace Microsoft.AspNet.Mvc
await actionResult.ExecuteResultAsync(_actionContext); await actionResult.ExecuteResultAsync(_actionContext);
} }
private void InitializeController(object controller, ModelStateDictionary modelState)
{
var controllerType = controller.GetType();
foreach (var prop in controllerType.GetRuntimeProperties())
{
if (prop.Name == "Context")
{
if (prop.PropertyType == typeof(HttpContext))
{
prop.SetValue(controller, _actionContext.HttpContext);
}
}
else if (prop.Name == "ModelState" && prop.PropertyType == typeof(ModelStateDictionary))
{
prop.SetValue(controller, modelState);
}
}
var method = controllerType.GetRuntimeMethods().FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
if (method == null)
{
return;
}
var args = method.GetParameters()
.Select(p => _serviceProvider.GetService(p.ParameterType)).ToArray();
method.Invoke(controller, args);
}
private async Task<IDictionary<string, object>> GetParameterValues(ModelStateDictionary modelState) private async Task<IDictionary<string, object>> GetParameterValues(ModelStateDictionary modelState)
{ {
var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(_actionContext); var actionBindingContext = await _bindingProvider.GetActionBindingContextAsync(_actionContext);