Eliminate use of method groups in PropertyHelper (dotnet/extensions#465)
* Eliminate use of method groups, and use for loop to enumerate elements of array.
Improves performance and reduces allocations.
* PR feedback:
Remove extra parentheses, and undo change from foreach to for loop.
* PR feedback
Revert change from for to foreach.
* var-ify TryGetValue out parameter.
\n\nCommit migrated from 08adb5c2ca
This commit is contained in:
parent
755b35295f
commit
83c88bd6bd
|
|
@ -7,7 +7,6 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.Internal
|
namespace Microsoft.Extensions.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -145,7 +144,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static PropertyHelper[] GetProperties(Type type)
|
public static PropertyHelper[] GetProperties(Type type)
|
||||||
{
|
{
|
||||||
return GetProperties(type, CreateInstance, PropertiesCache);
|
return GetProperties(type, p => CreateInstance(p), PropertiesCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -164,7 +163,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static PropertyHelper[] GetVisibleProperties(TypeInfo typeInfo)
|
public static PropertyHelper[] GetVisibleProperties(TypeInfo typeInfo)
|
||||||
{
|
{
|
||||||
return GetVisibleProperties(typeInfo.AsType(), CreateInstance, PropertiesCache, VisiblePropertiesCache);
|
return GetVisibleProperties(typeInfo.AsType(), p => CreateInstance(p), PropertiesCache, VisiblePropertiesCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -183,7 +182,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
/// </returns>
|
/// </returns>
|
||||||
public static PropertyHelper[] GetVisibleProperties(Type type)
|
public static PropertyHelper[] GetVisibleProperties(Type type)
|
||||||
{
|
{
|
||||||
return GetVisibleProperties(type, CreateInstance, PropertiesCache, VisiblePropertiesCache);
|
return GetVisibleProperties(type, p => CreateInstance(p), PropertiesCache, VisiblePropertiesCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -420,8 +419,7 @@ namespace Microsoft.Extensions.Internal
|
||||||
ConcurrentDictionary<Type, PropertyHelper[]> allPropertiesCache,
|
ConcurrentDictionary<Type, PropertyHelper[]> allPropertiesCache,
|
||||||
ConcurrentDictionary<Type, PropertyHelper[]> visiblePropertiesCache)
|
ConcurrentDictionary<Type, PropertyHelper[]> visiblePropertiesCache)
|
||||||
{
|
{
|
||||||
PropertyHelper[] result;
|
if (visiblePropertiesCache.TryGetValue(type, out var result))
|
||||||
if (visiblePropertiesCache.TryGetValue(type, out result))
|
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -497,18 +495,17 @@ namespace Microsoft.Extensions.Internal
|
||||||
// part of the sequence of properties returned by this method.
|
// part of the sequence of properties returned by this method.
|
||||||
type = Nullable.GetUnderlyingType(type) ?? type;
|
type = Nullable.GetUnderlyingType(type) ?? type;
|
||||||
|
|
||||||
PropertyHelper[] helpers;
|
if (!cache.TryGetValue(type, out var helpers))
|
||||||
if (!cache.TryGetValue(type, out helpers))
|
|
||||||
{
|
{
|
||||||
// We avoid loading indexed properties using the Where statement.
|
// We avoid loading indexed properties using the Where statement.
|
||||||
var properties = type.GetRuntimeProperties().Where(IsInterestingProperty);
|
var properties = type.GetRuntimeProperties().Where(p => IsInterestingProperty(p));
|
||||||
|
|
||||||
var typeInfo = type.GetTypeInfo();
|
var typeInfo = type.GetTypeInfo();
|
||||||
if (typeInfo.IsInterface)
|
if (typeInfo.IsInterface)
|
||||||
{
|
{
|
||||||
// Reflection does not return information about inherited properties on the interface itself.
|
// Reflection does not return information about inherited properties on the interface itself.
|
||||||
properties = properties.Concat(typeInfo.ImplementedInterfaces.SelectMany(
|
properties = properties.Concat(typeInfo.ImplementedInterfaces.SelectMany(
|
||||||
interfaceType => interfaceType.GetRuntimeProperties().Where(IsInterestingProperty)));
|
interfaceType => interfaceType.GetRuntimeProperties().Where(p => IsInterestingProperty(p))));
|
||||||
}
|
}
|
||||||
|
|
||||||
helpers = properties.Select(p => createPropertyHelper(p)).ToArray();
|
helpers = properties.Select(p => createPropertyHelper(p)).ToArray();
|
||||||
|
|
@ -518,17 +515,16 @@ namespace Microsoft.Extensions.Internal
|
||||||
return helpers;
|
return helpers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static bool IsInterestingProperty(PropertyInfo property)
|
private static bool IsInterestingProperty(PropertyInfo property)
|
||||||
{
|
{
|
||||||
// For improving application startup time, do not use GetIndexParameters() api early in this check as it
|
// For improving application startup time, do not use GetIndexParameters() api early in this check as it
|
||||||
// creates a copy of parameter array and also we would like to check for the presence of a get method
|
// creates a copy of parameter array and also we would like to check for the presence of a get method
|
||||||
// and short circuit asap.
|
// and short circuit asap.
|
||||||
return
|
return
|
||||||
property.GetMethod != null &&
|
property.GetMethod != null &&
|
||||||
property.GetMethod.IsPublic &&
|
property.GetMethod.IsPublic &&
|
||||||
!property.GetMethod.IsStatic &&
|
!property.GetMethod.IsStatic &&
|
||||||
|
|
||||||
// PropertyHelper can't work with ref structs.
|
// PropertyHelper can't work with ref structs.
|
||||||
!IsRefStructProperty(property) &&
|
!IsRefStructProperty(property) &&
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue