| | | 1 | | using System.Collections.Concurrent; |
| | | 2 | | |
| | | 3 | | // ReSharper disable once CheckNamespace |
| | | 4 | | namespace Elsa.Extensions; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Extends <see cref="Type"/> with additional methods. |
| | | 8 | | /// </summary> |
| | | 9 | | public static class TypeExtensions |
| | | 10 | | { |
| | 1 | 11 | | private static readonly ConcurrentDictionary<Type, string> SimpleAssemblyQualifiedTypeNameCache = new(); |
| | | 12 | | |
| | | 13 | | /// <summary> |
| | | 14 | | /// Gets the assembly-qualified name of the type, without version, culture, and public key token information. |
| | | 15 | | /// </summary> |
| | | 16 | | public static string GetSimpleAssemblyQualifiedName(this Type type) |
| | | 17 | | { |
| | 4697 | 18 | | if (type is null) throw new ArgumentNullException(nameof(type)); |
| | 4697 | 19 | | return SimpleAssemblyQualifiedTypeNameCache.GetOrAdd(type, BuildSimplifiedName); |
| | | 20 | | } |
| | | 21 | | |
| | | 22 | | /// <summary> |
| | | 23 | | /// Returns true of the type is generic, false otherwise. |
| | | 24 | | /// </summary> |
| | 5928 | 25 | | public static bool IsGenericType(this Type type, Type genericType) => type.IsGenericType && type.GetGenericTypeDefin |
| | | 26 | | |
| | | 27 | | /// <summary> |
| | | 28 | | /// Returns true of the type is nullable, false otherwise. |
| | | 29 | | /// </summary> |
| | 5928 | 30 | | public static bool IsNullableType(this Type type) => type.IsGenericType(typeof(Nullable<>)); |
| | | 31 | | |
| | | 32 | | /// <summary> |
| | | 33 | | /// Returns the wrapped type of the specified nullable type. |
| | | 34 | | /// </summary> |
| | 216 | 35 | | public static Type GetTypeOfNullable(this Type type) => type.GenericTypeArguments[0]; |
| | | 36 | | |
| | | 37 | | /// <summary> |
| | | 38 | | /// Returns true if the specified type is a collection type, false otherwise. |
| | | 39 | | /// </summary> |
| | | 40 | | public static bool IsCollectionType(this Type type) |
| | | 41 | | { |
| | 0 | 42 | | if (!type.IsGenericType) |
| | 0 | 43 | | return false; |
| | | 44 | | |
| | 0 | 45 | | var elementType = type.GenericTypeArguments[0]; |
| | 0 | 46 | | var collectionType = typeof(ICollection<>).MakeGenericType(elementType); |
| | 0 | 47 | | var listType = typeof(IList<>).MakeGenericType(elementType); |
| | 0 | 48 | | return collectionType.IsAssignableFrom(type) || listType.IsAssignableFrom(type); |
| | | 49 | | } |
| | | 50 | | |
| | | 51 | | /// <summary> |
| | | 52 | | /// Constructs a collection type from the specified type. |
| | | 53 | | /// </summary> |
| | 0 | 54 | | public static Type MakeCollectionType(this Type type) => typeof(ICollection<>).MakeGenericType(type); |
| | | 55 | | |
| | | 56 | | /// <summary> |
| | | 57 | | /// Returns the element type of the specified collection type. |
| | | 58 | | /// </summary> |
| | 0 | 59 | | public static Type GetCollectionElementType(this Type type) => type.GenericTypeArguments[0]; |
| | | 60 | | |
| | | 61 | | /// <summary> |
| | | 62 | | /// Determines whether the specified type is a numeric type. |
| | | 63 | | /// </summary> |
| | | 64 | | /// <param name="type">The type to check.</param> |
| | | 65 | | /// <returns>True if the specified type is numeric, otherwise false.</returns> |
| | | 66 | | public static bool IsNumericType(this Type type) |
| | | 67 | | { |
| | 18 | 68 | | return type.IsPrimitive || type == typeof(decimal) || type == typeof(float) || type == typeof(double) || type == |
| | | 69 | | } |
| | | 70 | | |
| | | 71 | | private static string BuildSimplifiedName(Type type) |
| | | 72 | | { |
| | 76 | 73 | | var assemblyName = type.Assembly.GetName().Name; |
| | | 74 | | |
| | 76 | 75 | | if (type.IsGenericType) |
| | | 76 | | { |
| | 0 | 77 | | var genericTypeName = type.GetGenericTypeDefinition().FullName!; |
| | 0 | 78 | | var backtickIndex = genericTypeName.IndexOf('`'); |
| | 0 | 79 | | var typeNameWithoutArity = genericTypeName[..backtickIndex]; |
| | 0 | 80 | | var arity = genericTypeName[backtickIndex..]; |
| | 0 | 81 | | var simplifiedGenericArguments = type.GetGenericArguments().Select(BuildSimplifiedName); |
| | | 82 | | |
| | 0 | 83 | | return $"{typeNameWithoutArity}{arity}[[{string.Join("],[", simplifiedGenericArguments)}]], {assemblyName}"; |
| | | 84 | | } |
| | | 85 | | |
| | 76 | 86 | | return $"{type.FullName}, {assemblyName}"; |
| | | 87 | | } |
| | | 88 | | } |