PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Fasterflect/Fasterflect/Extensions/Core/TypeExtensions.cs

#
C# | 223 lines | 137 code | 14 blank | 72 comment | 44 complexity | 6152eec5acdd59d0c47a3cedc997078d MD5 | raw file
  1. #region License
  2. // Copyright 2010 Buu Nguyen, Morten Mertner
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. // The latest version of this file can be found at http://fasterflect.codeplex.com/
  17. #endregion
  18. using System;
  19. using System.Linq;
  20. using System.Collections.Generic;
  21. namespace Fasterflect
  22. {
  23. /// <summary>
  24. /// Extension methods for inspecting types.
  25. /// </summary>
  26. public static class TypeExtensions
  27. {
  28. #region Implements
  29. /// <summary>
  30. /// Returns true if the supplied <paramref name="type"/> implements the given interface <typeparamref name="T"/>.
  31. /// </summary>
  32. /// <typeparam name="T">The type (interface) to check for.</typeparam>
  33. /// <param name="type">The type to check.</param>
  34. /// <returns>True if the given type implements the specified interface.</returns>
  35. /// <remarks>This method is for interfaces only. Use <seealso cref="Inherits"/> for class types and <seealso cref="InheritsOrImplements"/>
  36. /// to check both interfaces and classes.</remarks>
  37. public static bool Implements<T>( this Type type )
  38. {
  39. return type.Implements( typeof(T) );
  40. }
  41. /// <summary>
  42. /// Returns true of the supplied <paramref name="type"/> implements the given interface <paramref name="interfaceType"/>. If the given
  43. /// interface type is a generic type definition this method will use the generic type definition of any implemented interfaces
  44. /// to determine the result.
  45. /// </summary>
  46. /// <param name="interfaceType">The interface type to check for.</param>
  47. /// <param name="type">The type to check.</param>
  48. /// <returns>True if the given type implements the specified interface.</returns>
  49. /// <remarks>This method is for interfaces only. Use <seealso cref="Inherits"/> for classes and <seealso cref="InheritsOrImplements"/>
  50. /// to check both interfaces and classes.</remarks>
  51. public static bool Implements( this Type type, Type interfaceType )
  52. {
  53. if( type == null || interfaceType == null || type == interfaceType )
  54. return false;
  55. if( interfaceType.IsGenericTypeDefinition && type.GetInterfaces().Where( t => t.IsGenericType ).Select( t => t.GetGenericTypeDefinition() ).Any( gt => gt == interfaceType ) )
  56. {
  57. return true;
  58. }
  59. return interfaceType.IsAssignableFrom( type );
  60. }
  61. #endregion
  62. #region Inherits
  63. /// <summary>
  64. /// Returns true if the supplied <paramref name="type"/> inherits from the given class <typeparamref name="T"/>.
  65. /// </summary>
  66. /// <typeparam name="T">The type (class) to check for.</typeparam>
  67. /// <param name="type">The type to check.</param>
  68. /// <returns>True if the given type inherits from the specified class.</returns>
  69. /// <remarks>This method is for classes only. Use <seealso cref="Implements"/> for interface types and <seealso cref="InheritsOrImplements"/>
  70. /// to check both interfaces and classes.</remarks>
  71. public static bool Inherits<T>( this Type type )
  72. {
  73. return type.Inherits( typeof(T) );
  74. }
  75. /// <summary>
  76. /// Returns true if the supplied <paramref name="type"/> inherits from the given class <paramref name="baseType"/>.
  77. /// </summary>
  78. /// <param name="baseType">The type (class) to check for.</param>
  79. /// <param name="type">The type to check.</param>
  80. /// <returns>True if the given type inherits from the specified class.</returns>
  81. /// <remarks>This method is for classes only. Use <seealso cref="Implements"/> for interface types and <seealso cref="InheritsOrImplements"/>
  82. /// to check both interfaces and classes.</remarks>
  83. public static bool Inherits( this Type type, Type baseType )
  84. {
  85. if( baseType == null || type == null || type == baseType )
  86. return false;
  87. var rootType = typeof(object);
  88. if( baseType == rootType )
  89. return true;
  90. while( type != null && type != rootType )
  91. {
  92. var current = type.IsGenericType && baseType.IsGenericTypeDefinition ? type.GetGenericTypeDefinition() : type;
  93. if( baseType == current )
  94. return true;
  95. type = type.BaseType;
  96. }
  97. return false;
  98. }
  99. #endregion
  100. #region InheritsOrImplements
  101. /// <summary>
  102. /// Returns true if the supplied <paramref name="type"/> inherits from or implements the type <typeparamref name="T"/>.
  103. /// </summary>
  104. /// <typeparam name="T">The base type to check for.</typeparam>
  105. /// <param name="type">The type to check.</param>
  106. /// <returns>True if the given type inherits from or implements the specified base type.</returns>
  107. public static bool InheritsOrImplements<T>( this Type type )
  108. {
  109. return type.InheritsOrImplements( typeof(T) );
  110. }
  111. /// <summary>
  112. /// Returns true of the supplied <paramref name="type"/> inherits from or implements the type <paramref name="baseType"/>.
  113. /// </summary>
  114. /// <param name="baseType">The base type to check for.</param>
  115. /// <param name="type">The type to check.</param>
  116. /// <returns>True if the given type inherits from or implements the specified base type.</returns>
  117. public static bool InheritsOrImplements( this Type type, Type baseType )
  118. {
  119. if( type == null || baseType == null )
  120. return false;
  121. return baseType.IsInterface ? type.Implements( baseType ) : type.Inherits( baseType );
  122. }
  123. #endregion
  124. #region IsFrameworkType
  125. #region IsFrameworkType Helpers
  126. private static readonly List<byte[]> tokens = new List<byte[]>
  127. {
  128. new byte[] { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 },
  129. new byte[] { 0x31, 0xbf, 0x38, 0x56, 0xad, 0x36, 0x4e, 0x35 },
  130. new byte[] { 0xb0, 0x3f, 0x5f, 0x7f, 0x11, 0xd5, 0x0a, 0x3a }
  131. };
  132. internal class ByteArrayEqualityComparer : EqualityComparer<byte[]>
  133. {
  134. public override bool Equals( byte[] x, byte[] y )
  135. {
  136. return x != null && y != null && x.SequenceEqual( y );
  137. }
  138. public override int GetHashCode( byte[] obj )
  139. {
  140. return obj.GetHashCode();
  141. }
  142. }
  143. #endregion
  144. /// <summary>
  145. /// Returns true if the supplied type is defined in an assembly signed by Microsoft.
  146. /// </summary>
  147. public static bool IsFrameworkType( this Type type )
  148. {
  149. if( type == null )
  150. {
  151. throw new ArgumentNullException( "type" );
  152. }
  153. byte[] publicKeyToken = type.Assembly.GetName().GetPublicKeyToken();
  154. return publicKeyToken != null && tokens.Contains( publicKeyToken, new ByteArrayEqualityComparer() );
  155. }
  156. #endregion
  157. #region Name (with generic pretty-printing)
  158. /// <summary>
  159. /// Returns the C# name, including any generic parameters, of the supplied <paramref name="type"/>.
  160. /// </summary>
  161. /// <param name="type">The type to return the name for.</param>
  162. /// <returns>The type name formatted as you'd write it in C#.</returns>
  163. public static string Name( this Type type )
  164. {
  165. if( type.IsArray )
  166. {
  167. return string.Format( "{0}[]", type.GetElementType().Name() );
  168. }
  169. if( type.ContainsGenericParameters || type.IsGenericType )
  170. {
  171. if( type.BaseType == typeof(Nullable<>) || (type.BaseType == typeof(ValueType) && type.UnderlyingSystemType.Name.StartsWith( "Nullable" )) )
  172. {
  173. return GetCSharpTypeName( type.GetGenericArguments().Single().Name ) + "?";
  174. }
  175. int index = type.Name.IndexOf( "`" );
  176. string genericTypeName = index > 0 ? type.Name.Substring( 0, index ) : type.Name;
  177. string genericArgs = string.Join( ",", type.GetGenericArguments().Select( t => t.Name() ).ToArray() );
  178. return genericArgs.Length == 0 ? genericTypeName : genericTypeName + "<" + genericArgs + ">";
  179. }
  180. return GetCSharpTypeName( type.Name );
  181. }
  182. private static string GetCSharpTypeName( string typeName )
  183. {
  184. switch( typeName )
  185. {
  186. case "String":
  187. case "Object":
  188. case "Void":
  189. case "Byte":
  190. case "Double":
  191. case "Decimal":
  192. return typeName.ToLower();
  193. case "Int16":
  194. return "short";
  195. case "Int32":
  196. return "int";
  197. case "Int64":
  198. return "long";
  199. case "Single":
  200. return "float";
  201. case "Boolean":
  202. return "bool";
  203. default:
  204. return typeName;
  205. }
  206. }
  207. #endregion
  208. }
  209. }