[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.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
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>
public class CollectionModelBinder<TElement> : ICollectionModelBinder
{
private Func<object> _modelCreator;
/// <summary>
/// Creates a new <see cref="CollectionModelBinder{TElement}"/>.
/// </summary>
@ -147,7 +150,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
/// <returns>An instance of <paramref name="targetType"/>.</returns>
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

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Internal;
@ -15,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
public class ComplexTypeModelBinder : IModelBinder
{
private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
private Func<object> _modelCreator;
/// <summary>
/// Creates a new <see cref="ComplexTypeModelBinder"/>.
@ -316,9 +318,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
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.
return Activator.CreateInstance(bindingContext.ModelType);
if (_modelCreator == null)
{
_modelCreator = Expression
.Lambda<Func<object>>(Expression.New(bindingContext.ModelType))
.Compile();
}
return _modelCreator();
}
/// <summary>