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;
using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.AspNet.DependencyInjection; using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
@ -48,44 +47,20 @@ namespace Microsoft.AspNet.Mvc
private void InitializeController(object controller, ActionContext actionContext) private void InitializeController(object controller, ActionContext actionContext)
{ {
var controllerType = controller.GetType(); Injector.InjectProperty(controller, "ActionContext", actionContext);
foreach (var prop in controllerType.GetRuntimeProperties()) var viewData = new ViewDataDictionary<object>(
{ _serviceProvider.GetService<IModelMetadataProvider>(),
if(prop.Name == "ActionContext" && actionContext.ModelState);
prop.PropertyType.GetTypeInfo().IsAssignableFrom(typeof(ActionContext).GetTypeInfo())) Injector.InjectProperty(controller, "ViewData", viewData);
{
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);
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)); Injector.CallInitializer(controller, _serviceProvider);
if (method == null)
{
return;
}
var args = method.GetParameters()
.Select(p => _serviceProvider.GetService(p.ParameterType)).ToArray();
method.Invoke(controller, args);
} }
} }
} }

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;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.ExceptionServices; using System.Runtime.ExceptionServices;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -75,33 +74,14 @@ namespace Microsoft.AspNet.Mvc
var activator = _serviceProvider.GetService<ITypeActivator>(); var activator = _serviceProvider.GetService<ITypeActivator>();
object component = activator.CreateInstance(_serviceProvider, _componentType.AsType()); object component = activator.CreateInstance(_serviceProvider, _componentType.AsType());
foreach (var prop in _componentType.AsType().GetRuntimeProperties()) Injector.InjectProperty(component, "ViewContext", context);
{
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;
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() Injector.CallInitializer(component, _serviceProvider);
.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);
}
return component; return component;
} }