@@ -35,6 +35,8 @@ public static class TypeHelper
3535 private static readonly Type ArrayType = typeof ( Array ) ;
3636 private static readonly Type EnumType = typeof ( Enum ) ;
3737 private static readonly Type NullableType = typeof ( Nullable < > ) ;
38+ private static readonly int NullableTypeMetadataToken = NullableType . MetadataToken ;
39+ private static readonly Module NullableTypeModule = NullableType . Module ;
3840 private static readonly Type CompilerGeneratedAttributeType = typeof ( CompilerGeneratedAttribute ) ;
3941 private static readonly string TypeHelperNamespace = typeof ( TypeHelper ) . Namespace ;
4042
@@ -855,7 +857,7 @@ private static string GetShortNameBase(this Type type)
855857 /// <returns><see langword="True"/> if type is nullable type;
856858 /// otherwise, <see langword="false"/>.</returns>
857859 public static bool IsNullable ( this Type type ) =>
858- type . IsGenericType && ReferenceEquals ( type . GetGenericTypeDefinition ( ) , NullableType ) ;
860+ ( type . MetadataToken ^ NullableTypeMetadataToken ) == 0 && ReferenceEquals ( type . Module , NullableTypeModule ) ;
859861
860862 /// <summary>
861863 /// Indicates whether <typeparamref name="T"/> type is a <see cref="Nullable{T}"/> type.
@@ -890,34 +892,36 @@ public static bool IsNullable(this Type type) =>
890892 public static MethodInfo GetInvokeMethod ( this Type delegateType ) => delegateType . GetMethod ( invokeMethodName ) ;
891893
892894 /// <summary>
893- /// Determines whether the specified <paramref name="type"/> inherits the generic <paramref name="baseType"/>.
895+ /// Determines whether the specified <paramref name="type"/> is an ancestor or an instance of the
896+ /// provided <paramref name="openGenericBaseType"/>.
894897 /// </summary>
895898 /// <param name="type">The type to check.</param>
896- /// <param name="baseType ">Type of the generic.</param>
899+ /// <param name="openGenericBaseType ">Type of the generic. It is supposed this is an open generic type .</param>
897900 /// <returns>
898- /// <see langword="true"/> if the specified <paramref name="type"/> inherits the
899- /// generic <paramref name="baseType "/>; otherwise, <see langword="false"/>.
901+ /// <see langword="true"/> if the specified <paramref name="type"/> is an ancestor or an instance of the
902+ /// provided <paramref name="openGenericBaseType "/>; otherwise, <see langword="false"/>.
900903 /// </returns>
901- public static bool IsOfGenericType ( this Type type , Type baseType ) => GetGenericType ( type , baseType ) != null ;
904+ public static bool IsOfGenericType ( this Type type , Type openGenericBaseType ) =>
905+ GetGenericType ( type , openGenericBaseType ) != null ;
902906
903907 /// <summary>
904- /// Determines whether the specified <paramref name="type"/> inherits
905- /// the generic <paramref name="baseGenericTypeDefinition "/> and returns direct inheritor
906- /// of generic <paramref name="baseGenericTypeDefinition"/> if any .
908+ /// Determines whether the specified <paramref name="type"/> is an ancestor or an instance of
909+ /// the provided <paramref name="openGenericBaseType "/> and returns closed generic type with the
910+ /// specified type arguments if found .
907911 /// </summary>
908912 /// <param name="type">The type to check.</param>
909- /// <param name="baseGenericTypeDefinition">Type of the generic .</param>
913+ /// <param name="openGenericBaseType">Open generic type to be matched .</param>
910914 /// <returns>
911- /// Generic <see cref="Type"/> that directly inherits <paramref name="baseGenericTypeDefinition "/> if the
912- /// specified <paramref name=" type"/> inherits the generic <paramref name="baseGenericTypeDefinition "/>;
915+ /// A <see cref="Type"/> representing the closed generic version of <paramref name="openGenericBaseType "/>
916+ /// where type parameters are bound in case it exists in <paramref name="type "/>'s inheritance hierarchy ;
913917 /// otherwise, <see langword="null"/>.
914918 /// </returns>
915- public static Type GetGenericType ( this Type type , Type baseGenericTypeDefinition )
919+ public static Type GetGenericType ( this Type type , Type openGenericBaseType )
916920 {
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+ var definitionMetadataToken = openGenericBaseType . MetadataToken ;
922+ var definitionModule = openGenericBaseType . Module ;
923+ while ( type != null && ! ReferenceEquals ( type , ObjectType ) ) {
924+ if ( ( type . MetadataToken ^ definitionMetadataToken ) == 0 && ReferenceEquals ( type . Module , definitionModule ) ) {
921925 return type ;
922926 }
923927
@@ -928,31 +932,49 @@ public static Type GetGenericType(this Type type, Type baseGenericTypeDefinition
928932 }
929933
930934 /// <summary>
931- /// Determines whether <paramref name="type"/> implements the <paramref name="genericInterface"/>.
935+ /// Determines whether specified <paramref name="type"/> is an implementation of the
936+ /// provided <paramref name="openGenericInterface"/>.
932937 /// </summary>
933- /// <param name="type">The type.</param>
934- /// <param name="genericInterface">The <see langword="interface"/>.</param>
938+ /// <param name="type">A <see cref="Type"/> instance to be checked.</param>
939+ /// <param name="openGenericInterface">A <see cref="Type"/> of an open generic <see langword="interface"/>
940+ /// to match the specified <paramref name="type"/> against.</param>
941+ /// <returns>
942+ /// <see langword="true"/> if the specified <paramref name="type"/> is an implementation of the
943+ /// provided <paramref name="openGenericInterface"/>;
944+ /// otherwise, <see langword="false"/>.
945+ /// </returns>
946+ public static bool IsOfGenericInterface ( this Type type , Type openGenericInterface ) =>
947+ GetGenericInterface ( type , openGenericInterface ) != null ;
948+
949+ /// <summary>
950+ /// Determines whether the specified <paramref name="type"/> is an implementation of the
951+ /// provided <paramref name="openGenericInterface"/> and returns a <see cref="Type"/> instance
952+ /// for the closed generic interface where type arguments are specified if implementation is found.
953+ /// </summary>
954+ /// <param name="type">The type to be checked.</param>
955+ /// <param name="openGenericInterface">Open generic <see langword="interface"/> to be matched.</param>
935956 /// <returns>
936- /// <see langword="true"/> if the specified <paramref name="type"/> implements the
937- /// <paramref name="genericInterface"/>; otherwise, <see langword="false"/>.
957+ /// A <see cref="Type"/> representing closed generic version of <paramref name="openGenericInterface"/>
958+ /// where type parameters are bound in case it is implemented by the <paramref name="type"/>;
959+ /// otherwise, <see langword="null"/>.
938960 /// </returns>
939- public static bool IsOfGenericInterface ( this Type type , Type genericInterface )
961+ public static Type GetGenericInterface ( this Type type , Type openGenericInterface )
940962 {
941- var metadataToken = genericInterface . MetadataToken ;
942- var module = genericInterface . Module ;
943- if ( type . MetadataToken == metadataToken && ReferenceEquals ( type . Module , module ) ) {
944- return true ;
963+ var metadataToken = openGenericInterface . MetadataToken ;
964+ var module = openGenericInterface . Module ;
965+ if ( type == null || ( ( type . MetadataToken ^ metadataToken ) == 0 && ReferenceEquals ( type . Module , module ) ) ) {
966+ return type ;
945967 }
946968
947969 // We don't use LINQ as we don't want to create a closure here
948970 foreach ( var implementedInterface in type . GetInterfaces ( ) ) {
949971 if ( ( implementedInterface . MetadataToken ^ metadataToken ) == 0
950972 && ReferenceEquals ( implementedInterface . Module , module ) ) {
951- return true ;
973+ return implementedInterface ;
952974 }
953975 }
954976
955- return false ;
977+ return null ;
956978 }
957979
958980 /// <summary>
0 commit comments