ActivatorUtilities.CreateInstance: allocation optimization
\n\nCommit migrated from 689a832ced
This commit is contained in:
parent
73e95c56c1
commit
f402cc566a
|
|
@ -43,43 +43,45 @@ namespace Microsoft.Extensions.Internal
|
||||||
int bestLength = -1;
|
int bestLength = -1;
|
||||||
var seenPreferred = false;
|
var seenPreferred = false;
|
||||||
|
|
||||||
ConstructorMatcher bestMatcher = null;
|
ConstructorMatcher bestMatcher = default;
|
||||||
|
|
||||||
if (!instanceType.GetTypeInfo().IsAbstract)
|
if (!instanceType.GetTypeInfo().IsAbstract)
|
||||||
{
|
{
|
||||||
foreach (var constructor in instanceType
|
foreach (var constructor in instanceType
|
||||||
.GetTypeInfo()
|
.GetTypeInfo()
|
||||||
.DeclaredConstructors
|
.DeclaredConstructors)
|
||||||
.Where(c => !c.IsStatic && c.IsPublic))
|
|
||||||
{
|
{
|
||||||
var matcher = new ConstructorMatcher(constructor);
|
if (!constructor.IsStatic && constructor.IsPublic)
|
||||||
var isPreferred = constructor.IsDefined(typeof(ActivatorUtilitiesConstructorAttribute), false);
|
|
||||||
var length = matcher.Match(parameters);
|
|
||||||
|
|
||||||
if (isPreferred)
|
|
||||||
{
|
{
|
||||||
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)
|
seenPreferred |= isPreferred;
|
||||||
{
|
|
||||||
bestLength = length;
|
|
||||||
bestMatcher = matcher;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.";
|
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);
|
throw new InvalidOperationException(message);
|
||||||
|
|
@ -327,18 +329,16 @@ namespace Microsoft.Extensions.Internal
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ConstructorMatcher
|
private struct ConstructorMatcher
|
||||||
{
|
{
|
||||||
private readonly ConstructorInfo _constructor;
|
private readonly ConstructorInfo _constructor;
|
||||||
private readonly ParameterInfo[] _parameters;
|
private readonly ParameterInfo[] _parameters;
|
||||||
private readonly object[] _parameterValues;
|
private readonly object[] _parameterValues;
|
||||||
private readonly bool[] _parameterValuesSet;
|
|
||||||
|
|
||||||
public ConstructorMatcher(ConstructorInfo constructor)
|
public ConstructorMatcher(ConstructorInfo constructor)
|
||||||
{
|
{
|
||||||
_constructor = constructor;
|
_constructor = constructor;
|
||||||
_parameters = _constructor.GetParameters();
|
_parameters = _constructor.GetParameters();
|
||||||
_parameterValuesSet = new bool[_parameters.Length];
|
|
||||||
_parameterValues = new object[_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)
|
for (var applyIndex = applyIndexStart; givenMatched == false && applyIndex != _parameters.Length; ++applyIndex)
|
||||||
{
|
{
|
||||||
if (_parameterValuesSet[applyIndex] == false &&
|
if (_parameterValues[applyIndex] == null &&
|
||||||
_parameters[applyIndex].ParameterType.GetTypeInfo().IsAssignableFrom(givenType))
|
_parameters[applyIndex].ParameterType.GetTypeInfo().IsAssignableFrom(givenType))
|
||||||
{
|
{
|
||||||
givenMatched = true;
|
givenMatched = true;
|
||||||
_parameterValuesSet[applyIndex] = true;
|
|
||||||
_parameterValues[applyIndex] = givenParameters[givenIndex];
|
_parameterValues[applyIndex] = givenParameters[givenIndex];
|
||||||
if (applyIndexStart == applyIndex)
|
if (applyIndexStart == applyIndex)
|
||||||
{
|
{
|
||||||
|
|
@ -382,7 +381,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
{
|
{
|
||||||
for (var index = 0; index != _parameters.Length; index++)
|
for (var index = 0; index != _parameters.Length; index++)
|
||||||
{
|
{
|
||||||
if (_parameterValuesSet[index] == false)
|
if (_parameterValues[index] == null)
|
||||||
{
|
{
|
||||||
var value = provider.GetService(_parameters[index].ParameterType);
|
var value = provider.GetService(_parameters[index].ParameterType);
|
||||||
if (value == null)
|
if (value == null)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue