[Perf] Replace Activator.CreateInstance with cached delegate in Model Binders

Fixes Part1 of #4470
This commit is contained in:
mnltejaswini 2016-04-27 15:19:03 -07:00
parent fa29396141
commit 0e4b838864
2 changed files with 24 additions and 3 deletions

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.Internal;
@ -20,6 +21,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
/// <typeparam name="TElement">Type of elements in the collection.</typeparam> /// <typeparam name="TElement">Type of elements in the collection.</typeparam>
public class CollectionModelBinder<TElement> : ICollectionModelBinder public class CollectionModelBinder<TElement> : ICollectionModelBinder
{ {
private Func<object> _modelCreator;
/// <summary> /// <summary>
/// Creates a new <see cref="CollectionModelBinder{TElement}"/>. /// Creates a new <see cref="CollectionModelBinder{TElement}"/>.
/// </summary> /// </summary>
@ -147,7 +150,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
/// <returns>An instance of <paramref name="targetType"/>.</returns> /// <returns>An instance of <paramref name="targetType"/>.</returns>
protected object CreateInstance(Type targetType) protected object CreateInstance(Type targetType)
{ {
return Activator.CreateInstance(targetType); if (_modelCreator == null)
{
_modelCreator = Expression
.Lambda<Func<object>>(Expression.New(targetType))
.Compile();
}
return _modelCreator();
} }
// Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value // Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.Internal;
@ -15,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
public class ComplexTypeModelBinder : IModelBinder public class ComplexTypeModelBinder : IModelBinder
{ {
private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders; private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
private Func<object> _modelCreator;
/// <summary> /// <summary>
/// Creates a new <see cref="ComplexTypeModelBinder"/>. /// Creates a new <see cref="ComplexTypeModelBinder"/>.
@ -316,9 +318,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
throw new ArgumentNullException(nameof(bindingContext)); throw new ArgumentNullException(nameof(bindingContext));
} }
// If the Activator throws an exception, we want to propagate it back up the call stack, since the // If model creator throws an exception, we want to propagate it back up the call stack, since the
// application developer should know that this was an invalid type to try to bind to. // application developer should know that this was an invalid type to try to bind to.
return Activator.CreateInstance(bindingContext.ModelType); if (_modelCreator == null)
{
_modelCreator = Expression
.Lambda<Func<object>>(Expression.New(bindingContext.ModelType))
.Compile();
}
return _modelCreator();
} }
/// <summary> /// <summary>