Skip to content

Commit e5af27a

Browse files
committed
Improve TypeHelper.GetGenericType & TypeHelper.IsOfGenericInterface methods performance
1 parent 0fe8319 commit e5af27a

1 file changed

Lines changed: 34 additions & 17 deletions

File tree

Orm/Xtensive.Orm/Reflection/TypeHelper.cs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -902,41 +902,58 @@ public static bool IsNullable(this Type type) =>
902902

903903
/// <summary>
904904
/// Determines whether the specified <paramref name="type"/> inherits
905-
/// the generic <paramref name="baseType"/> and returns direct inheritor
906-
/// of generic <paramref name="baseType"/> if any.
905+
/// the generic <paramref name="baseGenericTypeDefinition"/> and returns direct inheritor
906+
/// of generic <paramref name="baseGenericTypeDefinition"/> if any.
907907
/// </summary>
908908
/// <param name="type">The type to check.</param>
909-
/// <param name="baseType">Type of the generic.</param>
909+
/// <param name="baseGenericTypeDefinition">Type of the generic.</param>
910910
/// <returns>
911-
/// Generic <see cref="Type"/> that directly inherits <paramref name="baseType"/> if the
912-
/// specified <paramref name="type"/> inherits the generic <paramref name="baseType"/>;
911+
/// Generic <see cref="Type"/> that directly inherits <paramref name="baseGenericTypeDefinition"/> if the
912+
/// specified <paramref name="type"/> inherits the generic <paramref name="baseGenericTypeDefinition"/>;
913913
/// otherwise, <see langword="null"/>.
914914
/// </returns>
915-
public static Type GetGenericType(this Type type, Type baseType)
915+
public static Type GetGenericType(this Type type, Type baseGenericTypeDefinition)
916916
{
917-
var t = type;
918-
while (!(t == null || t == ObjectType)) {
919-
if (t.IsGenericType && t.GetGenericTypeDefinition() == baseType) {
920-
return t;
917+
var definitionMetadataToken = baseGenericTypeDefinition.MetadataToken;
918+
var definitionModule = baseGenericTypeDefinition.Module;
919+
while (!(type == null || type == ObjectType)) {
920+
if ((type.MetadataToken ^ definitionMetadataToken)==0 && ReferenceEquals(type.Module, definitionModule)) {
921+
return type;
921922
}
922923

923-
t = t.BaseType;
924+
type = type.BaseType;
924925
}
925926

926927
return null;
927928
}
928929

929930
/// <summary>
930-
/// Determines whether <paramref name="type"/> implements the <paramref name="interface"/>.
931+
/// Determines whether <paramref name="type"/> implements the <paramref name="genericInterface"/>.
931932
/// </summary>
932933
/// <param name="type">The type.</param>
933-
/// <param name="interface">The <see langword="interface"/>.</param>
934+
/// <param name="genericInterface">The <see langword="interface"/>.</param>
934935
/// <returns>
935-
/// <see langword="true"/> if the specified <paramref name="type"/> implements the <paramref name="interface"/>;
936-
/// otherwise, <see langword="false"/>.
936+
/// <see langword="true"/> if the specified <paramref name="type"/> implements the
937+
/// <paramref name="genericInterface"/>; otherwise, <see langword="false"/>.
937938
/// </returns>
938-
public static bool IsOfGenericInterface(this Type type, Type @interface) =>
939-
type.IsOfGenericType(@interface) || type.GetInterfaces().Any(t => t.IsOfGenericType(@interface));
939+
public static bool IsOfGenericInterface(this Type type, Type genericInterface)
940+
{
941+
var metadataToken = genericInterface.MetadataToken;
942+
var module = genericInterface.Module;
943+
if (type.MetadataToken == metadataToken && ReferenceEquals(type.Module, module)) {
944+
return true;
945+
}
946+
947+
// We don't use LINQ as we don't want to create a closure here
948+
foreach (var implementedInterface in type.GetInterfaces()) {
949+
if ((implementedInterface.MetadataToken ^ metadataToken) == 0
950+
&& ReferenceEquals(implementedInterface.Module, module)) {
951+
return true;
952+
}
953+
}
954+
955+
return false;
956+
}
940957

941958
/// <summary>
942959
/// Converts <paramref name="type"/> to type that can assign both

0 commit comments

Comments
 (0)