|
@@ -0,0 +1,460 @@
|
|
|
+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;
|
|
|
+
|
|
|
+namespace ServiceCenter.Extensions
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 类型转换扩展
|
|
|
+ /// </summary>
|
|
|
+ public static class TypeExtension
|
|
|
+ {
|
|
|
+ /// <summary>
|
|
|
+ /// 将字符串转换为short
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value">需要转换的字符串</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static short ToShort(this string value)
|
|
|
+ {
|
|
|
+ return Convert.ToInt16(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 将int转换为short
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value">需要转换的字符串</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static short ToShort(this int value)
|
|
|
+ {
|
|
|
+ return Convert.ToInt16(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 将decimal转换为short
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value">需要转换的字符串</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static short ToShort(this decimal value)
|
|
|
+ {
|
|
|
+ return Convert.ToInt16(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 将字符串转换为int
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value">需要转换的字符串</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static int ToInt(this string value)
|
|
|
+ {
|
|
|
+ return Convert.ToInt32(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 判断值为奇数/偶数
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value">需要判断的值</param>
|
|
|
+ /// <returns> true:是奇数 false:是偶数</returns>
|
|
|
+ public static bool OddNumberOrEven(this short value)
|
|
|
+ {
|
|
|
+ return value % 2 != 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取short类型Code,只限设备组
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static short GetShortCode(this string value)
|
|
|
+ {
|
|
|
+ return value.Replace("G", "").ToShort();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 数据映射
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="D"></typeparam>
|
|
|
+ /// <typeparam name="S"></typeparam>
|
|
|
+ /// <param name="s"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static D Mapper<D, S>(S s)
|
|
|
+ {
|
|
|
+ var d = Activator.CreateInstance<D>();
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取字典
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="T1"></typeparam>
|
|
|
+ /// <typeparam name="T2"></typeparam>
|
|
|
+ /// <typeparam name="T3"></typeparam>
|
|
|
+ /// <param name="t3"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static Dictionary<string, object> EntityClassToDictionary<T>(T t)
|
|
|
+ {
|
|
|
+ var type = typeof(SugarColumn);
|
|
|
+ Dictionary<string, object> d = new Dictionary<string, object>();
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取MD5字符串
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="myString"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// DataTable转换成实体类
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="T"></typeparam>
|
|
|
+ /// <param name="dt"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static List<object> TableToEntity(this DataTable dt, string typeName)
|
|
|
+ {
|
|
|
+ var list = new List<object>();
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 转换到目标类型
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="value"></param>
|
|
|
+ /// <typeparam name="T"></typeparam>
|
|
|
+ /// <returns></returns>
|
|
|
+ internal static T ConvertTo<T>(this object value) => (T)typeof(T).FromObject(value);
|
|
|
+
|
|
|
+ private static ConcurrentDictionary<Type, Func<string, object>> _dicFromObject = new ConcurrentDictionary<Type, Func<string, object>>();
|
|
|
+
|
|
|
+ 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<Type, ConstructorInfo> _dicInternalGetTypeConstructor0OrFirst = new ConcurrentDictionary<Type, ConstructorInfo>();
|
|
|
+
|
|
|
+ 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();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|