using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Znyc.Recruitment.Admin.Commons.Data; namespace Znyc.Recruitment.Admin.Commons.Extensions { /// /// 类型辅助扩展方法类 /// public static class TypeExtensions { /// /// 判断当前类型是否可由指定类型派生 /// public static bool IsDeriveClassFrom(this Type type, bool canAbstract = false) { return IsDeriveClassFrom(type, typeof(TBaseType), canAbstract); } /// /// 判断当前类型是否可由指定类型派生 /// public static bool IsDeriveClassFrom(this Type type, Type baseType, bool canAbstract = false) { Check.NotNull(type, nameof(type)); Check.NotNull(baseType, nameof(baseType)); return type.IsClass && !canAbstract && !type.IsAbstract && type.IsBaseOn(baseType); } /// /// 判断类型是否为Nullable类型 /// /// 要处理的类型 /// 是返回True,不是返回False public static bool IsNullableType(this Type type) { return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); } /// /// 由类型的Nullable类型返回实际类型 /// /// 要处理的类型对象 /// public static Type GetNonNullableType(this Type type) { if (IsNullableType(type)) { return type.GetGenericArguments()[0]; } return type; } /// /// 通过类型转换器获取Nullable类型的基础类型 /// /// 要处理的类型对象 /// public static Type GetUnNullableType(this Type type) { if (IsNullableType(type)) { NullableConverter nullableConverter = new NullableConverter(type); return nullableConverter.UnderlyingType; } return type; } /// /// 获取类型的Description特性描述信息 /// /// 类型对象 /// 是否搜索类型的继承链以查找描述特性 /// 返回Description特性描述信息,如不存在则返回类型的全名 public static string GetDescription(this Type type, bool inherit = true) { DescriptionAttribute desc = type.GetAttribute(inherit); return desc == null ? type.FullName : desc.Description; } /// /// 获取成员元数据的Description特性描述信息 /// /// 成员元数据对象 /// 是否搜索成员的继承链以查找描述特性 /// 返回Description特性描述信息,如不存在则返回成员的名称 public static string GetDescription(this MemberInfo member, bool inherit = true) { DescriptionAttribute desc = member.GetAttribute(inherit); if (desc != null) { return desc.Description; } DisplayNameAttribute displayName = member.GetAttribute(inherit); if (displayName != null) { return displayName.DisplayName; } DisplayAttribute display = member.GetAttribute(inherit); if (display != null) { return display.Name; } return member.Name; } /// /// 检查指定指定类型成员中是否存在指定的Attribute特性 /// /// 要检查的Attribute特性类型 /// 要检查的类型成员 /// 是否从继承中查找 /// 是否存在 public static bool HasAttribute(this MemberInfo memberInfo, bool inherit = true) where T : Attribute { return memberInfo.IsDefined(typeof(T), inherit); } /// /// 从类型成员获取指定Attribute特性 /// /// Attribute特性类型 /// 类型类型成员 /// 是否从继承中查找 /// 存在返回第一个,不存在返回null public static T GetAttribute(this MemberInfo memberInfo, bool inherit = true) where T : Attribute { object[] attributes = memberInfo.GetCustomAttributes(typeof(T), inherit); return attributes.FirstOrDefault() as T; } /// /// 从类型成员获取指定Attribute特性 /// /// Attribute特性类型 /// 类型类型成员 /// 是否从继承中查找 /// 返回所有指定Attribute特性的数组 public static T[] GetAttributes(this MemberInfo memberInfo, bool inherit = true) where T : Attribute { return memberInfo.GetCustomAttributes(typeof(T), inherit).Cast().ToArray(); } /// /// 判断类型是否为集合类型 /// /// 要处理的类型 /// 是返回True,不是返回False public static bool IsEnumerable(this Type type) { if (type == typeof(string)) { return false; } return typeof(IEnumerable).IsAssignableFrom(type); } /// /// 判断当前泛型类型是否可由指定类型的实例填充 /// /// 泛型类型 /// 指定类型 /// public static bool IsGenericAssignableFrom(this Type genericType, Type type) { genericType.CheckNotNull("genericType"); type.CheckNotNull("type"); if (!genericType.IsGenericType) { throw new ArgumentException("该功能只支持泛型类型的调用,非泛型类型可使用 IsAssignableFrom 方法。"); } List allOthers = new List { type }; if (genericType.IsInterface) { allOthers.AddRange(type.GetInterfaces()); } foreach (Type other in allOthers) { Type cur = other; while (cur != null) { if (cur.IsGenericType) { cur = cur.GetGenericTypeDefinition(); } if (cur.IsSubclassOf(genericType) || cur == genericType) { return true; } cur = cur.BaseType; } } return false; } /// /// 方法是否是异步 /// public static bool IsAsync(this MethodInfo method) { return method.ReturnType == typeof(Task) || method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>); } /// /// 返回当前类型是否是指定基类的派生类 /// /// 当前类型 /// 要判断的基类型 /// public static bool IsBaseOn(this Type type, Type baseType) { if (baseType.IsGenericTypeDefinition) { return baseType.IsGenericAssignableFrom(type); } return baseType.IsAssignableFrom(type); } /// /// 返回当前类型是否是指定基类的派生类 /// /// 要判断的基类型 /// 当前类型 /// public static bool IsBaseOn(this Type type) { Type baseType = typeof(TBaseType); return type.IsBaseOn(baseType); } /// /// 获取类型的全名,附带所在类库 /// public static string GetFullNameWithModule(this Type type) { return $"{type.FullName},{type.Module.Name.Replace(".dll", "").Replace(".exe", "")}"; } /// /// 获取类型的显示短名称 /// public static string ShortDisplayName(this Type type) { return type.DisplayName(false); } /// /// 获取类型的显示名称 /// public static string DisplayName([NotNull] this Type type, bool fullName = true) { StringBuilder sb = new StringBuilder(); ProcessType(sb, type, fullName); return sb.ToString(); } /// /// 获取主键字段 /// /// /// public static PropertyInfo GetKeyProperty(this Type entity) { return entity.GetProperties().GetKeyProperty(); } /// /// /// /// public static PropertyInfo GetKeyProperty(this PropertyInfo[] properties) { return properties.Where(c => c.IsKey()).FirstOrDefault(); } /// /// /// /// public static bool IsKey(this PropertyInfo propertyInfo) { object[] keyAttributes = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), false); if (keyAttributes.Length > 0) { return true; } return false; } #region 私有方法 private static readonly Dictionary _builtInTypeNames = new() { { typeof(bool), "bool" }, { typeof(byte), "byte" }, { typeof(char), "char" }, { typeof(decimal), "decimal" }, { typeof(double), "double" }, { typeof(float), "float" }, { typeof(int), "int" }, { typeof(long), "long" }, { typeof(object), "object" }, { typeof(sbyte), "sbyte" }, { typeof(short), "short" }, { typeof(string), "string" }, { typeof(uint), "uint" }, { typeof(ulong), "ulong" }, { typeof(ushort), "ushort" }, { typeof(void), "void" } }; private static void ProcessType(StringBuilder builder, Type type, bool fullName) { if (type.IsGenericType) { Type[] genericArguments = type.GetGenericArguments(); ProcessGenericType(builder, type, genericArguments, genericArguments.Length, fullName); } else if (type.IsArray) { ProcessArrayType(builder, type, fullName); } else if (_builtInTypeNames.TryGetValue(type, out string builtInName)) { builder.Append(builtInName); } else if (!type.IsGenericParameter) { builder.Append(fullName ? type.FullName : type.Name); } } private static void ProcessArrayType(StringBuilder builder, Type type, bool fullName) { Type innerType = type; while (innerType.IsArray) { innerType = innerType.GetElementType(); } ProcessType(builder, innerType, fullName); while (type.IsArray) { builder.Append('['); builder.Append(',', type.GetArrayRank() - 1); builder.Append(']'); type = type.GetElementType(); } } private static void ProcessGenericType(StringBuilder builder, Type type, Type[] genericArguments, int length, bool fullName) { int offset = type.IsNested ? type.DeclaringType.GetGenericArguments().Length : 0; if (fullName) { if (type.IsNested) { ProcessGenericType(builder, type.DeclaringType, genericArguments, offset, fullName); builder.Append('+'); } else { builder.Append(type.Namespace); builder.Append('.'); } } int genericPartIndex = type.Name.IndexOf('`'); if (genericPartIndex <= 0) { builder.Append(type.Name); return; } builder.Append(type.Name, 0, genericPartIndex); builder.Append('<'); for (int i = offset; i < length; i++) { ProcessType(builder, genericArguments[i], fullName); if (i + 1 == length) { continue; } builder.Append(','); if (!genericArguments[i + 1].IsGenericParameter) { builder.Append(' '); } } builder.Append('>'); } #endregion 私有方法 } }