ActivatorUtilities.CreateInstance: allocation optimization

\n\nCommit migrated from 689a832ced
This commit is contained in:
Yves Marx 2019-06-05 08:19:46 +02:00
parent 73e95c56c1
commit f402cc566a
1 changed files with 25 additions and 26 deletions

View File

@ -43,43 +43,45 @@ namespace Microsoft.Extensions.Internal
int bestLength = -1;
var seenPreferred = false;
ConstructorMatcher bestMatcher = null;
ConstructorMatcher bestMatcher = default;
if (!instanceType.GetTypeInfo().IsAbstract)
{
foreach (var constructor in instanceType
.GetTypeInfo()
.DeclaredConstructors
.Where(c => !c.IsStatic && c.IsPublic))
.DeclaredConstructors)
{
var matcher = new ConstructorMatcher(constructor);
var isPreferred = constructor.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), false);
var length = matcher.Match(parameters);
if (isPreferred)
if (!constructor.IsStatic && constructor.IsPublic)
{
if (seenPreferred)
var matcher = new ConstructorMatcher(constructor);
var isPreferred = constructor.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), false);
var length = matcher.Match(parameters);
if (isPreferred)
{
ThrowMultipleCtorsMarkedWithAttributeException();
if (seenPreferred)
{
ThrowMultipleCtorsMarkedWithAttributeException();
}
if (length == -1)
{
ThrowMarkedCtorDoesNotTakeAllProvidedArguments();
}
}
if (length == -1)
if (isPreferred || bestLength < length)
{
ThrowMarkedCtorDoesNotTakeAllProvidedArguments();
bestLength = length;
bestMatcher = matcher;
}
}
if (isPreferred || bestLength < length)
{
bestLength = length;
bestMatcher = matcher;
seenPreferred |= isPreferred;
}
seenPreferred |= isPreferred;
}
}
if (bestMatcher == null)
if (bestLength == -1)
{
var message = $"A suitable constructor for type '{instanceType}' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.";
throw new InvalidOperationException(message);
@ -327,18 +329,16 @@ namespace Microsoft.Extensions.Internal
return true;
}
private class ConstructorMatcher
private struct ConstructorMatcher
{
private readonly ConstructorInfo _constructor;
private readonly ParameterInfo[] _parameters;
private readonly object[] _parameterValues;
private readonly bool[] _parameterValuesSet;
public ConstructorMatcher(ConstructorInfo constructor)
{
_constructor = constructor;
_parameters = _constructor.GetParameters();
_parameterValuesSet = new bool[_parameters.Length];
_parameterValues = new object[_parameters.Length];
}
@ -353,11 +353,10 @@ namespace Microsoft.Extensions.Internal
for (var applyIndex = applyIndexStart; givenMatched == false && applyIndex != _parameters.Length; ++applyIndex)
{
if (_parameterValuesSet[applyIndex] == false &&
if (_parameterValues[applyIndex] == null &&
_parameters[applyIndex].ParameterType.GetTypeInfo().IsAssignableFrom(givenType))
{
givenMatched = true;
_parameterValuesSet[applyIndex] = true;
_parameterValues[applyIndex] = givenParameters[givenIndex];
if (applyIndexStart == applyIndex)
{
@ -382,7 +381,7 @@ namespace Microsoft.Extensions.Internal
{
for (var index = 0; index != _parameters.Length; index++)
{
if (_parameterValuesSet[index] == false)
if (_parameterValues[index] == null)
{
var value = provider.GetService(_parameters[index].ParameterType);
if (value == null)