Patternizing our property injection/initializer

This commit is contained in:
Ryan Nowak 2014-03-25 14:00:15 -07:00
parent 8ed5b7b079
commit 21e48be06e
3 changed files with 70 additions and 62 deletions

View File

@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -48,44 +47,20 @@ namespace Microsoft.AspNet.Mvc
private void InitializeController(object controller, ActionContext actionContext)
{
var controllerType = controller.GetType();
Injector.InjectProperty(controller, "ActionContext", actionContext);
foreach (var prop in controllerType.GetRuntimeProperties())
{
if(prop.Name == "ActionContext" &&
prop.PropertyType.GetTypeInfo().IsAssignableFrom(typeof(ActionContext).GetTypeInfo()))
{
prop.SetValue(controller, actionContext);
}
else if (prop.Name == "ViewData" &&
prop.PropertyType.GetTypeInfo().IsAssignableFrom(typeof(ViewDataDictionary<object>).GetTypeInfo()))
{
prop.SetValue(controller, new ViewDataDictionary<object>(
_serviceProvider.GetService<IModelMetadataProvider>(), actionContext.ModelState));
}
else if (prop.Name == "Url" &&
prop.PropertyType.GetTypeInfo().IsAssignableFrom(typeof(IUrlHelper).GetTypeInfo()))
{
var urlHelper = new UrlHelper(
actionContext.HttpContext,
actionContext.Router,
actionContext.RouteValues);
var viewData = new ViewDataDictionary<object>(
_serviceProvider.GetService<IModelMetadataProvider>(),
actionContext.ModelState);
Injector.InjectProperty(controller, "ViewData", viewData);
prop.SetValue(controller, urlHelper);
}
}
var urlHelper = new UrlHelper(
actionContext.HttpContext,
actionContext.Router,
actionContext.RouteValues);
Injector.InjectProperty(controller, "Url", 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);
Injector.CallInitializer(controller, _serviceProvider);
}
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNet.DependencyInjection;
namespace Microsoft.AspNet.Mvc
{
public static class Injector
{
public static void CallInitializer([NotNull] object obj, [NotNull] IServiceProvider services)
{
var type = obj.GetType();
var initializeMethod =
type.GetRuntimeMethods()
.FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
if (initializeMethod == null)
{
return;
}
var args =
initializeMethod.GetParameters()
.Select(p => services.GetService(p.ParameterType))
.ToArray();
initializeMethod.Invoke(obj, args);
}
public static void InjectProperty<TProperty>([NotNull] object obj, [NotNull] string propertyName, TProperty value)
{
var type = obj.GetType();
var property = type.GetProperty(propertyName);
if (property.PropertyType.IsAssignableFrom(typeof(TProperty)))
{
property.SetValue(obj, value);
}
}
public static void InjectProperty<TProperty>([NotNull] object obj, [NotNull] string propertyName, [NotNull] IServiceProvider services)
{
var type = obj.GetType();
var property = type.GetProperty(propertyName);
if (property.PropertyType.IsAssignableFrom(typeof(TProperty)))
{
property.SetValue(obj, services.GetService<TProperty>());
}
}
}
}

View File

@ -1,6 +1,5 @@

using System;
using System.Linq;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
@ -75,33 +74,14 @@ namespace Microsoft.AspNet.Mvc
var activator = _serviceProvider.GetService<ITypeActivator>();
object component = activator.CreateInstance(_serviceProvider, _componentType.AsType());
foreach (var prop in _componentType.AsType().GetRuntimeProperties())
{
if (prop.Name == "ViewContext" &&
typeof(ViewContext).GetTypeInfo().IsAssignableFrom(prop.PropertyType.GetTypeInfo()))
{
prop.SetValue(component, context);
}
else if (prop.Name == "ViewData" &&
typeof(ViewDataDictionary).GetTypeInfo().IsAssignableFrom(prop.PropertyType.GetTypeInfo()))
{
// We're flowing the viewbag across, but the concept of model doesn't really apply here
var viewData = new ViewDataDictionary(context.ViewData);
viewData.Model = null;
Injector.InjectProperty(component, "ViewContext", context);
prop.SetValue(component, viewData);
}
}
// We're flowing the viewbag across, but the concept of model doesn't really apply here
var viewData = new ViewDataDictionary(context.ViewData);
viewData.Model = null;
Injector.InjectProperty(component, "ViewData", viewData);
var method = _componentType.AsType().GetRuntimeMethods()
.FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.OrdinalIgnoreCase));
if (method != null)
{
var args = method.GetParameters()
.Select(p => _serviceProvider.GetService(p.ParameterType)).ToArray();
method.Invoke(component, args);
}
Injector.CallInitializer(component, _serviceProvider);
return component;
}