aspnetcore/src/Microsoft.AspNet.Mvc.Core/DefaultControllerFactory.cs

90 lines
3.0 KiB
C#

using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc
{
public class DefaultControllerFactory : IControllerFactory
{
private readonly ITypeActivator _activator;
private readonly IServiceProvider _serviceProvider;
public DefaultControllerFactory(IServiceProvider serviceProvider, ITypeActivator activator)
{
_serviceProvider = serviceProvider;
_activator = activator;
}
public object CreateController(ActionContext actionContext, ModelStateDictionary modelState)
{
var actionDescriptor = actionContext.ActionDescriptor as ReflectedActionDescriptor;
if (actionDescriptor == null)
{
return null;
}
try
{
var controller = _activator.CreateInstance(actionDescriptor.ControllerDescriptor.ControllerTypeInfo.AsType());
// TODO: How do we feed the controller with context (need DI improvements)
InitializeController(controller, actionContext, modelState);
return controller;
}
catch (ReflectionTypeLoadException)
{
}
return null;
}
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);
}
else if (prop.Name == "Url" && prop.PropertyType == typeof(IUrlHelper))
{
var urlHelper = new UrlHelper(
actionContext.HttpContext,
actionContext.Router,
actionContext.RouteValues);
prop.SetValue(controller, urlHelper);
}
}
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);
}
}
}