using Newtonsoft.Json; using SqlSugar; using System.Collections.Concurrent; using System.ComponentModel; using System.Data; using System.Globalization; using System.Numerics; using System.Reflection; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; namespace ServiceCenter.Extensions { /// /// 类型转换扩展 /// public static class TypeExtension { /// /// 将字符串转换为short /// /// 需要转换的字符串 /// public static short ToShort(this string value) { return Convert.ToInt16(value); } /// /// 将int转换为short /// /// 需要转换的字符串 /// public static short ToShort(this int value) { return Convert.ToInt16(value); } /// /// 将decimal转换为short /// /// 需要转换的字符串 /// public static short ToShort(this decimal value) { return Convert.ToInt16(value); } /// /// 将字符串转换为int /// /// 需要转换的字符串 /// public static int ToInt(this string value) { return Convert.ToInt32(value); } /// /// 获取最后一位数字 /// /// 字符串 /// public static int GetLastDigit(this string value) { return Convert.ToInt32(Regex.Match(value, @"\d+$").Value); } /// /// 判断值为奇数/偶数 /// /// 需要判断的值 /// true:是奇数 false:是偶数 public static bool OddNumberOrEven(this short value) { return value % 2 != 0; } /// /// 获取short类型Code,只限设备组 /// /// /// public static short GetShortCode(this string value) { return value.Replace("G", "").ToShort(); } /// /// 扩展方法,获得枚举的Description /// /// 枚举值 /// 当枚举值没有定义DescriptionAttribute,是否使用枚举名代替,默认是使用 /// 枚举的Description public static string GetDescription(this Enum value, Boolean nameInstead = true) { Type type = value.GetType(); string name = Enum.GetName(type, value); if (name == null) { return null; } FieldInfo field = type.GetField(name); DescriptionAttribute attribute = System.Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (attribute == null && nameInstead == true) { return name; } return attribute?.Description; } /// /// 获取属性的描述信息 /// public static string GetDescription(this Type type, string proName) { PropertyInfo pro = type.GetProperty(proName); string des = proName; if (pro != null) { des = pro.GetDescription(); } return des; } public static string JsonToString(this object value) { return JsonConvert.SerializeObject(value); } /// /// 获取属性的描述信息 /// public static string GetDescription(this MemberInfo info) { var attrs = (DescriptionAttribute[])info.GetCustomAttributes(typeof(DescriptionAttribute), false); string des = info.Name; foreach (DescriptionAttribute attr in attrs) { des = attr.Description; } return des; } /// /// 数据映射 /// /// 映射目标实体Type /// /// /// public static D Mapper(this S s) { var d = Activator.CreateInstance(); var sType = s?.GetType(); var dType = typeof(D); foreach (var sP in sType.GetProperties()) { foreach (var dP in dType.GetProperties()) { if (dP.Name == sP.Name) { dP.SetValue(d, sP.GetValue(s)); break; } } } return d; } public static object Copy(this object obj, object type) { foreach (var p in type.GetType().GetProperties()) { var p2 = obj.GetType().GetProperty(p.Name); if (p2 != null && p2.PropertyType == p.PropertyType) { var a = p2.GetValue(obj); p.SetValue(type, p2.GetValue(obj)); } } return type; } public static object Copy(this object obj, Type type) { var res = Activator.CreateInstance(type); foreach (var p in type.GetProperties()) { var p2 = obj.GetType().GetProperty(p.Name); if (p2 != null) { var value = p2.GetValue(obj); p.SetValue(res, value); } } return res; } //public static object Copy(this object source, Type t) //{ // var obj = Activator.CreateInstance(t); // foreach (var p in t.GetProperties()) // { // var p2 = source.GetType().GetProperty(p.Name); // var value = p2.GetValue(source); // p.SetValue(obj, value); // } // return obj; //} /// /// 获取字典 /// /// /// /// /// /// public static Dictionary EntityClassToDictionary(T t) { var type = typeof(SugarColumn); Dictionary d = new Dictionary(); var sType = t.GetType(); foreach (var sP in sType.GetProperties()) { if (sP.CustomAttributes.Any(v => v.AttributeType == type) && sP.Name != "VER" && sP.Name != "ID") { d.Add(sP.Name, sP.GetValue(t)); } } return d; } /// /// 获取MD5字符串 /// /// /// public static string GetMD5(this string myString) { var md5 = MD5.Create(); var fromData = Encoding.Unicode.GetBytes(myString); var targetData = md5.ComputeHash(fromData); string byte2String = null; for (var i = 0; i < targetData.Length; i++) { byte2String += targetData[i].ToString("x"); } return byte2String; } /// /// DataTable转换成实体类 /// /// /// /// public static List TableToEntity(this DataTable dt, string typeName) { var list = new List(); try { foreach (DataRow row in dt.Rows) { var entity = Type.GetType(typeName); PropertyInfo[] pArray = entity.GetType().GetProperties(); foreach (var p in pArray) { if (dt.Columns.Contains(p.Name)) { if (!p.CanWrite) continue; var value = row[p.Name]; if (value != DBNull.Value) { var targetType = p.PropertyType; var convertType = targetType; if (targetType.IsGenericType && targetType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { //可空类型 var nullableConverter = new NullableConverter(targetType); convertType = nullableConverter.UnderlyingType; } if (!string.IsNullOrEmpty(convertType.FullName) && !string.IsNullOrEmpty(value.ToString())) { value = Convert.ChangeType(value, convertType); } switch (convertType.FullName) { case "System.Decimal": p.SetValue(entity, Convert.ToDecimal(value), null); break; case "System.String": p.SetValue(entity, Convert.ToString(value), null); break; case "System.Int32": p.SetValue(entity, Convert.ToInt32(value), null); break; case "System.Int64": p.SetValue(entity, Convert.ToInt64(value), null); break; case "System.Int16": p.SetValue(entity, Convert.ToInt16(value), null); break; case "System.Double": p.SetValue(entity, Convert.ToDouble(value), null); break; case "System.Single": p.SetValue(entity, Convert.ToSingle(value), null); break; case "System.DateTime": p.SetValue(entity, Convert.ToDateTime(value), null); break; default: p.SetValue(entity, value, null); break; } } } } list.Add(entity); } } catch (Exception ex) { } return list; } /// /// 转换到目标类型 /// /// /// /// internal static T ConvertTo(this object value) => (T)typeof(T).FromObject(value); public static string yyyy(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyy); } public static string yyyyMM(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMM); } public static string yyyyMMdd(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMMdd); } public static string yyyyMMddhh(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMMddhh); } public static string yyyyMMddhhmm(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMMddhhmm); } public static string yyyyMMddhhmmss(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMMddhhmmss); } public static string yyyyMMddhhmmssf(this DateTime time) { return time.GetFormat(GetFormatterEnum.yyyyMMddhhmmssfffffff); } /// /// 获取指定格式时间的字符串 /// /// 时间 /// 类型 /// public static string GetFormat(this DateTime time, GetFormatterEnum formatterEnum) { switch (formatterEnum) { case GetFormatterEnum.Default: return time.ToString(); case GetFormatterEnum.yyyy: return time.ToString("yyyy"); case GetFormatterEnum.yyyyMM: return time.ToString("yyyy-MM"); case GetFormatterEnum.yyyyMMdd: return time.ToString("yyyy-MM-dd"); case GetFormatterEnum.yyyyMMddhh: return time.ToString("yyyy-MM-dd HH"); case GetFormatterEnum.yyyyMMddhhmm: return time.ToString("yyyy-MM-dd HH:mm"); case GetFormatterEnum.yyyyMMddhhmmss: return time.ToString("yyyy-MM-dd HH:mm:ss"); case GetFormatterEnum.yyyyMMddhhmmssfffffff: return time.ToString("yyyy-MM-dd HH:mm:ss:fffffff"); case GetFormatterEnum.only: return time.ToString("yyyyMMddHHmmssfffffff"); default: return time.ToString(); } } private static ConcurrentDictionary> _dicFromObject = new ConcurrentDictionary>(); public static object FromObject(this Type targetType, object value, Encoding encoding = null) { if (targetType == typeof(object)) return value; if (encoding == null) encoding = Encoding.UTF8; var valueIsNull = value == null; var valueType = valueIsNull ? typeof(string) : value.GetType(); if (valueType == targetType) return value; if (valueType == typeof(byte[])) //byte[] -> guid { if (targetType == typeof(Guid)) { var bytes = value as byte[]; return Guid.TryParse(BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 36)).Replace("-", ""), out var tryguid) ? tryguid : Guid.Empty; } if (targetType == typeof(Guid?)) { var bytes = value as byte[]; return Guid.TryParse(BitConverter.ToString(bytes, 0, Math.Min(bytes.Length, 36)).Replace("-", ""), out var tryguid) ? (Guid?)tryguid : null; } } if (targetType == typeof(byte[])) //guid -> byte[] { if (valueIsNull) return null; if (valueType == typeof(Guid) || valueType == typeof(Guid?)) { var bytes = new byte[16]; var guidN = ((Guid)value).ToString("N"); for (var a = 0; a < guidN.Length; a += 2) bytes[a / 2] = byte.Parse($"{guidN[a]}{guidN[a + 1]}", NumberStyles.HexNumber); return bytes; } return encoding.GetBytes(value.ToInvariantCultureToString()); } else if (targetType.IsArray) { if (value is Array valueArr) { var targetElementType = targetType.GetElementType(); var sourceArrLen = valueArr.Length; var target = Array.CreateInstance(targetElementType, sourceArrLen); for (var a = 0; a < sourceArrLen; a++) target.SetValue(targetElementType.FromObject(valueArr.GetValue(a), encoding), a); return target; } //if (value is IList valueList) //{ // var targetElementType = targetType.GetElementType(); // var sourceArrLen = valueList.Count; // var target = Array.CreateInstance(targetElementType, sourceArrLen); // for (var a = 0; a < sourceArrLen; a++) target.SetValue(targetElementType.FromObject(valueList[a], encoding), a); // return target; //} } var func = _dicFromObject.GetOrAdd(targetType, tt => { if (tt == typeof(object)) return vs => vs; if (tt == typeof(string)) return vs => vs; if (tt == typeof(char[])) return vs => vs == null ? null : vs.ToCharArray(); if (tt == typeof(char)) return vs => vs == null ? default(char) : vs.ToCharArray(0, 1).FirstOrDefault(); if (tt == typeof(bool)) return vs => { if (vs == null) return false; switch (vs.ToLower()) { case "true": case "1": return true; } return false; }; if (tt == typeof(bool?)) return vs => { if (vs == null) return false; switch (vs.ToLower()) { case "true": case "1": return true; case "false": case "0": return false; } return null; }; if (tt == typeof(byte)) return vs => vs == null ? 0 : byte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(byte?)) return vs => vs == null ? null : byte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (byte?)tryval : null; if (tt == typeof(decimal)) return vs => vs == null ? 0 : decimal.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(decimal?)) return vs => vs == null ? null : decimal.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (decimal?)tryval : null; if (tt == typeof(double)) return vs => vs == null ? 0 : double.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(double?)) return vs => vs == null ? null : double.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (double?)tryval : null; if (tt == typeof(float)) return vs => vs == null ? 0 : float.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(float?)) return vs => vs == null ? null : float.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (float?)tryval : null; if (tt == typeof(int)) return vs => vs == null ? 0 : int.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(int?)) return vs => vs == null ? null : int.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (int?)tryval : null; if (tt == typeof(long)) return vs => vs == null ? 0 : long.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(long?)) return vs => vs == null ? null : long.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (long?)tryval : null; if (tt == typeof(sbyte)) return vs => vs == null ? 0 : sbyte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(sbyte?)) return vs => vs == null ? null : sbyte.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (sbyte?)tryval : null; if (tt == typeof(short)) return vs => vs == null ? 0 : short.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(short?)) return vs => vs == null ? null : short.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (short?)tryval : null; if (tt == typeof(uint)) return vs => vs == null ? 0 : uint.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(uint?)) return vs => vs == null ? null : uint.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (uint?)tryval : null; if (tt == typeof(ulong)) return vs => vs == null ? 0 : ulong.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(ulong?)) return vs => vs == null ? null : ulong.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (ulong?)tryval : null; if (tt == typeof(ushort)) return vs => vs == null ? 0 : ushort.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(ushort?)) return vs => vs == null ? null : ushort.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (ushort?)tryval : null; if (tt == typeof(DateTime)) return vs => vs == null ? DateTime.MinValue : DateTime.TryParse(vs, out var tryval) ? tryval : DateTime.MinValue; if (tt == typeof(DateTime?)) return vs => vs == null ? null : DateTime.TryParse(vs, out var tryval) ? (DateTime?)tryval : null; if (tt == typeof(DateTimeOffset)) return vs => vs == null ? DateTimeOffset.MinValue : DateTimeOffset.TryParse(vs, out var tryval) ? tryval : DateTimeOffset.MinValue; if (tt == typeof(DateTimeOffset?)) return vs => vs == null ? null : DateTimeOffset.TryParse(vs, out var tryval) ? (DateTimeOffset?)tryval : null; if (tt == typeof(TimeSpan)) return vs => vs == null ? TimeSpan.Zero : TimeSpan.TryParse(vs, out var tryval) ? tryval : TimeSpan.Zero; if (tt == typeof(TimeSpan?)) return vs => vs == null ? null : TimeSpan.TryParse(vs, out var tryval) ? (TimeSpan?)tryval : null; if (tt == typeof(Guid)) return vs => vs == null ? Guid.Empty : Guid.TryParse(vs, out var tryval) ? tryval : Guid.Empty; if (tt == typeof(Guid?)) return vs => vs == null ? null : Guid.TryParse(vs, out var tryval) ? (Guid?)tryval : null; if (tt == typeof(BigInteger)) return vs => vs == null ? 0 : BigInteger.TryParse(vs, NumberStyles.Any, null, out var tryval) ? tryval : 0; if (tt == typeof(BigInteger?)) return vs => vs == null ? null : BigInteger.TryParse(vs, NumberStyles.Any, null, out var tryval) ? (BigInteger?)tryval : null; if (tt.NullableTypeOrThis().IsEnum) { var tttype = tt.NullableTypeOrThis(); var ttdefval = tt.CreateInstanceGetDefaultValue(); return vs => { if (string.IsNullOrWhiteSpace(vs)) return ttdefval; return Enum.Parse(tttype, vs, true); }; } var localTargetType = targetType; var localValueType = valueType; return vs => { if (vs == null) return null; throw new NotSupportedException($"convert failed {localValueType.DisplayCsharp()} -> {localTargetType.DisplayCsharp()}"); }; }); var valueStr = valueIsNull ? null : valueType == typeof(byte[]) ? encoding.GetString(value as byte[]) : value.ToInvariantCultureToString(); return func(valueStr); } internal static string ToInvariantCultureToString(this object obj) => obj is string objstr ? objstr : string.Format(CultureInfo.InvariantCulture, @"{0}", obj); private static bool IsNullableType(this Type that) => that.IsArray == false && that?.FullName.StartsWith("System.Nullable`1[") == true; private static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GetGenericArguments().First() : that; internal static object CreateInstanceGetDefaultValue(this Type that) { if (that == null) return null; if (that == typeof(string)) return default(string); if (that == typeof(Guid)) return default(Guid); if (that == typeof(byte[])) return default(byte[]); if (that.IsArray) return Array.CreateInstance(that.GetElementType(), 0); if (that.IsInterface || that.IsAbstract) return null; var ctorParms = that.InternalGetTypeConstructor0OrFirst(false)?.GetParameters(); if (ctorParms == null || ctorParms.Any() == false) return Activator.CreateInstance(that, true); return Activator.CreateInstance(that, ctorParms.Select(a => a.ParameterType.IsInterface || a.ParameterType.IsAbstract || a.ParameterType == typeof(string) || a.ParameterType.IsArray ? null : Activator.CreateInstance(a.ParameterType, null)).ToArray()); } private static ConcurrentDictionary _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary(); private static ConstructorInfo InternalGetTypeConstructor0OrFirst(this Type that, bool isThrow = true) { var ret = _dicInternalGetTypeConstructor0OrFirst.GetOrAdd(that, tp => tp.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[0], null) ?? tp.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault()); if (ret == null && isThrow) throw new ArgumentException($"{that.FullName} has no method to access constructor"); return ret; } private static string DisplayCsharp(this Type type, bool isNameSpace = true) { if (type == null) return null; if (type == typeof(void)) return "void"; if (type.IsGenericParameter) return type.Name; if (type.IsArray) return $"{DisplayCsharp(type.GetElementType())}[]"; var sb = new StringBuilder(); var nestedType = type; while (nestedType.IsNested) { sb.Insert(0, ".").Insert(0, DisplayCsharp(nestedType.DeclaringType, false)); nestedType = nestedType.DeclaringType; } if (isNameSpace && string.IsNullOrWhiteSpace(nestedType.Namespace) == false) sb.Insert(0, ".").Insert(0, nestedType.Namespace); if (type.IsGenericType == false) return sb.Append(type.Name).ToString(); var genericParameters = type.GetGenericArguments(); if (type.IsNested && type.DeclaringType.IsGenericType) { var dic = genericParameters.ToDictionary(a => a.Name); foreach (var nestedGenericParameter in type.DeclaringType.GetGenericArguments()) if (dic.ContainsKey(nestedGenericParameter.Name)) dic.Remove(nestedGenericParameter.Name); genericParameters = dic.Values.ToArray(); } if (genericParameters.Any() == false) return sb.Append(type.Name).ToString(); sb.Append(type.Name.Remove(type.Name.IndexOf('`'))).Append("<"); var genericTypeIndex = 0; foreach (var genericType in genericParameters) { if (genericTypeIndex++ > 0) sb.Append(", "); sb.Append(DisplayCsharp(genericType, true)); } return sb.Append(">").ToString(); } /// /// 对象转换为字典 /// /// /// /// public static Dictionary ToDic(this T obj) where T : class { Dictionary map = new Dictionary(); var objSte = JsonConvert.SerializeObject(obj); map = JsonConvert.DeserializeObject>(objSte); return map; } /// /// 字典转为实体 /// /// /// /// public static T ToClass(this Dictionary obj) { var objSte = JsonConvert.SerializeObject(obj); var map = JsonConvert.DeserializeObject(objSte); return map; } } public enum GetFormatterEnum { /// /// 默认类型 /// Default = 0, /// /// yyyy /// yyyy = 4, /// /// yyyy-MM /// yyyyMM = 5, /// /// yyyy-MM-dd /// yyyyMMdd = 6, /// /// yyyy-MM-dd hh /// yyyyMMddhh = 7, /// /// yyyy-MM-dd hh:mm /// yyyyMMddhhmm = 8, /// /// yyyy-MM-dd hh:mm:ss /// yyyyMMddhhmmss = 9, /// /// yyyy-MM-dd hh:mm:ss:fffffff /// yyyyMMddhhmmssfffffff = 10, /// /// 用时间组成唯一值 /// yyyyMMddhhmmssfffffff /// only = 11, } }