• .NET常用的扩展方法整理


    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Text.RegularExpressions;
    
    namespace IBO.XJMYQP.Utility
    {
        public static class Extension
        {
            #region String Extension
    
            public static string[] Split(this string val, string code)
            {
                return Regex.Split(val, code);
            }
    
            public static bool IsNullOrEmpty(this string val)
            {
                return string.IsNullOrEmpty(val);
            }
    
            public static bool IsNotEmpty(this string val)
            {
                return !string.IsNullOrEmpty(val);
            }
    
            public static string ToString2(this object val)
            {
                if (val == null)
                    return string.Empty;
                return val.ToString();
            }
    
            /// <summary>
            /// 将1900-01-01或 0001/1/1 转换为空字符串 
            /// </summary>
            /// <param name="val"></param>
            /// <returns></returns>
            public static string ToVaildDateTime(this object val)
            {
                if (val == null)
                    return string.Empty;
                else if (val.ToString() == "0001/1/1 0:00:00")
                    return string.Empty;
                else if (val.ToString() == "1900-01-01 00:00:00.000" || val.ToString() == "1900/1/1 0:00:00")
                    return string.Empty;
                return val.ToString();
            }
    
            /// <summary>
            /// 将空值和NULL值转换为一个默认的时间1900-01-01
            /// </summary>
            /// <param name="val"></param>
            /// <returns></returns>
            public static string ToInVaildDateTime(this object val)
            {
                if (val == null)
                    return "1900-01-01";
                else if (val.ToString2().IsNullOrEmpty())
                    return "1900-01-01";
                return val.ToString();
            }
    
            /// <summary>
            /// 判断字符串是否是数字
            /// </summary>
            public static bool IsNumeral(this string val)
            {
                decimal i = 0;
                return decimal.TryParse(val, out i);
            }
    
            /// <summary>
            /// 清除空格,加入非空判断,空字符串调用也不会报错
            /// </summary>
            public static string TrimSpace(this string val)
            {
                if (val == null)
                    return null;
                else
                    return val.Trim();
            }
    
            public static bool Contains(this string val, string value, StringComparison comp)
            {
                return val.IndexOf(value, comp) >= 0;
            }
    
            public static DateTime? ToDateTime(this string val)
            {
                if (string.IsNullOrEmpty(val)) return null;
                DateTime dt;
                if (DateTime.TryParse(val, out dt))
                {
                    return dt;
                }
                return null;
            }
    
            public static bool ToBoolean(this string val)
            {
                if (string.IsNullOrEmpty(val)) return false;
                return val == Boolean.TrueString;
            }
    
            public static int ToInt(this string val)
            {
                int intValue;
                if (int.TryParse(val, out intValue))
                {
                    return intValue;
                }
                return 0;
            }
    
            public static long ToLong(this string val)
            {
                long intValue;
                if (long.TryParse(val, out intValue))
                {
                    return intValue;
                }
                return 0;
            }
    
            public static decimal ToDecimal(this string val)
            {
                decimal intValue;
                if (decimal.TryParse(val, out intValue))
                {
                    return intValue;
                }
                return 0;
            }
    
            public static double ToDouble(this string val)
            {
                double result;
                if (double.TryParse(val, out result))
                {
                    return result;
                }
                return 0;
            }
    
            public static float ToFloat(this string val)
            {
                float result;
                if (float.TryParse(val, out result))
                {
                    return result;
                }
                return 0;
            }
    
            /// <summary>
            /// 按照长度截取字符串
            /// </summary>
            /// <param name="val"></param>
            /// <param name="length"></param>
            /// <returns></returns>
            public static string Truncate(this string val, int length)
            {
                if (string.IsNullOrEmpty(val))
                    return val;
                return (val.Length > length ? val.Substring(0, length - 1) : val);
            }
    
            /// <summary>
            /// 按照长度截取字符串
            /// </summary>
            /// <param name="val"></param>
            /// <param name="length"></param>
            /// <param name="coda">结尾符号</param>
            /// <returns></returns>
            public static string Truncate(this string val, int length, string coda)
            {
                if (string.IsNullOrEmpty(val))
                    return val;
                return (val.Length > length ? val.Substring(0, length - 1) + coda : val);
            }
    
            public static int ParseDayOfWeek(this string val)
            {
                val = val.ToLower();
                switch (val)
                {
                    case "monday":
                        return 1;
                    case "tuesday":
                        return 2;
                    case "wednesday":
                        return 3;
                    case "thursday":
                        return 4;
                    case "friday":
                        return 5;
                    case "saturday":
                        return 6;
                    case "sunday":
                        return 7;
                    default:
                        return 0;
                }
            }
    
            /// <summary>
            /// 截取指定字节长度的字符串
            /// </summary>
            /// <param name="str">原字符串</param>
            /// <param name="len">截取字节长度</param>
            /// <returns></returns>
            public static string CutByteString(this string str, int len)
            {
                string result = string.Empty;// 最终返回的结果
                if (string.IsNullOrEmpty(str)) { return result; }
                int byteLen = System.Text.Encoding.Default.GetByteCount(str);// 单字节字符长度
                int charLen = str.Length;// 把字符平等对待时的字符串长度
                int byteCount = 0;// 记录读取进度
                int pos = 0;// 记录截取位置
                if (byteLen > len)
                {
                    for (int i = 0; i < charLen; i++)
                    {
                        if (Convert.ToInt32(str.ToCharArray()[i]) > 255)// 按中文字符计算加2
                        { byteCount += 2; }
                        else// 按英文字符计算加1
                        { byteCount += 1; }
                        if (byteCount > len)// 超出时只记下上一个有效位置
                        {
                            pos = i;
                            break;
                        }
                        else if (byteCount == len)// 记下当前位置
                        {
                            pos = i + 1;
                            break;
                        }
                    }
                    if (pos >= 0)
                    { result = str.Substring(0, pos); }
                }
                else
                { result = str; }
                return result;
            }
    
    
            /// <summary>
            /// 截取指定字节长度的字符串
            /// </summary>
            /// <param name="str">原字符串</param>
            /// <param name="startIndex">起始位置</param>
            /// <param name="len">截取字节长度</param>
            /// <returns></returns>
            public static string CutByteString(this string str, int startIndex, int len)
            {
                string result = string.Empty;// 最终返回的结果
                if (string.IsNullOrEmpty(str)) { return result; }
    
                int byteLen = System.Text.Encoding.Default.GetByteCount(str);// 单字节字符长度
                int charLen = str.Length;// 把字符平等对待时的字符串长度
    
                if (startIndex == 0)
                { return CutByteString(str, len); }
                else if (startIndex >= byteLen)
                { return result; }
                else //startIndex < byteLen
                {
                    int AllLen = startIndex + len;
                    int byteCountStart = 0;// 记录读取进度
                    int byteCountEnd = 0;// 记录读取进度
                    int startpos = 0;// 记录截取位置                
                    int endpos = 0;// 记录截取位置
                    for (int i = 0; i < charLen; i++)
                    {
                        if (Convert.ToInt32(str.ToCharArray()[i]) > 255)// 按中文字符计算加2
                        { byteCountStart += 2; }
                        else// 按英文字符计算加1
                        { byteCountStart += 1; }
                        if (byteCountStart > startIndex)// 超出时只记下上一个有效位置
                        {
                            startpos = i;
                            AllLen = startIndex + len - 1;
                            break;
                        }
                        else if (byteCountStart == startIndex)// 记下当前位置
                        {
                            startpos = i + 1;
                            break;
                        }
                    }
    
                    if (startIndex + len <= byteLen)//截取字符在总长以内
                    {
                        for (int i = 0; i < charLen; i++)
                        {
                            if (Convert.ToInt32(str.ToCharArray()[i]) > 255)// 按中文字符计算加2
                            { byteCountEnd += 2; }
                            else// 按英文字符计算加1
                            { byteCountEnd += 1; }
                            if (byteCountEnd > AllLen)// 超出时只记下上一个有效位置
                            {
                                endpos = i;
                                break;
                            }
                            else if (byteCountEnd == AllLen)// 记下当前位置
                            {
                                endpos = i + 1;
                                break;
                            }
                        }
                        endpos = endpos - startpos;
                    }
                    else if (startIndex + len > byteLen)//截取字符超出总长
                    {
                        endpos = charLen - startpos;
                    }
                    if (endpos >= 0)
                    { result = str.Substring(startpos, endpos); }
                }
                return result;
            }
    
    
            #endregion
    
            #region Object Extension
    
            public static DateTime? ToDateTime(this object val)
            {
                if (val == null) return null;
                return val.ToString().ToDateTime();
            }
    
            public static DateTime ToDateTime2(this object val)
            {
                if (val == null) return DateTime.MinValue;
                var time = val.ToString().ToDateTime();
                return time.HasValue ? time.Value : DateTime.MinValue;
            }
    
            public static Guid ToGuid(this object val)
            {
                //=>3.5没有提供Guid.TryParse 方法。
                if (val == null) return Guid.Empty;
                Guid gd;
                try
                {
                    gd = new Guid(val.ToString2());
                    return gd;
                }
                catch
                {
                    return Guid.Empty;
                }
            }
    
            public static bool ToBoolean(this object val)
            {
                if (val == null) return false;
                return val.ToString().ToBoolean();
            }
    
            public static int ToInt(this object val)
            {
                if (val == null) return 0;
                return val.ToString().ToInt();
            }
    
            public static long ToLong(this object val)
            {
                if (val == null) return 0;
                return val.ToString().ToLong();
            }
    
    
            public static int ToIndexInt(this object val)
            {
                if (val == null) return -1;
                return val.ToString().ToInt();
            }
    
            public static decimal ToDecimal(this object val)
            {
                if (val == null) return 0;
                return val.ToString().ToDecimal();
            }
    
            public static double ToDouble(this object val)
            {
                if (val == null) return 0;
                return val.ToString().ToDouble();
            }
            public static float ToFloat(this object val)
            {
                if (val == null) return 0;
                return val.ToString().ToFloat();
            }
    
            /// <summary> 
            /// 对象转换为Json 
            /// </summary> 
            /// <param name="jsonObject">对象</param> 
            /// <returns>Json字符串</returns> 
            public static string ToJson(this object jsonObject)
            {
                string jsonString = "{";
                PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties();
                for (int i = 0; i < propertyInfo.Length; i++)
                {
                    object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null);
                    string value = string.Empty;
                    if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan)
                    {
                        value = "'" + objectValue.ToString() + "'";
                    }
                    else if (objectValue is string)
                    {
                        value = "'" + ToJson(objectValue.ToString()) + "'";
                    }
                    else if (objectValue is IEnumerable)
                    {
                        value = ToJson((IEnumerable)objectValue);
                    }
                    else
                    {
                        value = ToJson(objectValue.ToString());
                    }
                    jsonString += """ + ToJson(propertyInfo[i].Name) + "":" + value + ",";
                }
                jsonString.Remove(jsonString.Length - 1, jsonString.Length);
                return jsonString + "}";
            }
    
            #endregion
    
            #region Numeral Extension
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this decimal val, decimal start, decimal end)
            {
                return val >= start && val <= end;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this int val, int start, int end)
            {
                return val >= start && val <= end;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this float val, float start, float end)
            {
                return val >= start && val <= end;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this double val, double start, double end)
            {
                return val >= start && val <= end;
            }
    
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this decimal? val, decimal start, decimal end)
            {
                return val.HasValue ? (val >= start && val <= end) : false;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this int? val, int start, int end)
            {
                return val.HasValue ? (val >= start && val <= end) : false;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this float? val, float start, float end)
            {
                return val.HasValue ? (val >= start && val <= end) : false;
            }
            /// <summary>
            /// 是否在指定范围内
            /// </summary>
            /// <param name="start">起始数值</param>
            /// <param name="end">结束数值</param>
            public static bool Between(this double? val, double start, double end)
            {
                return val.HasValue ? (val >= start && val <= end) : false;
            }
    
            #endregion
    
            #region Data Extension
            /// <summary>
            /// 通用简单实体类型互转
            /// </summary>
            public static List<ResultType> ConvertToEntityList<ResultType>(this object list) where ResultType : new()
            {
                List<ResultType> ResultList = new List<ResultType>();
                if (list == null) return ResultList;
                Type fromObj = list.GetType();
                if (fromObj.Equals(typeof(DataTable)))
                {
                    var dt = list as DataTable;
                    ResultList = dt.Rows.Cast<DataRow>().Where(m => !(m.RowState == DataRowState.Deleted || m.RowState == DataRowState.Detached)).Select(m => m.ConvertToEntityByDataRow<ResultType>()).ToList();
                }
                else if (list is IEnumerable)
                {
                    ResultList = ((IList)list).Cast<object>().Select(m => m.ConvertToEntity<ResultType>()).ToList();
                }
                return ResultList;
            }
    
            /// <summary>
            /// 通用简单实体类型互转
            /// </summary>
            public static ResultType ConvertToEntity<ResultType>(this object fromEntity) where ResultType : new()
            {
                ResultType t = new ResultType();
                Type fromObj = fromEntity.GetType();
                if (fromObj.Equals(typeof(DataRow)))
                {
                    //DataRow类型
                    DataRow dr = fromEntity as DataRow;
                    t = dr.ConvertToEntityByDataRow<ResultType>();
                }
                else
                {
                    Type type = typeof(ResultType);
                    PropertyInfo[] properties = type.GetProperties();
                    PropertyInfo[] fromProperties = fromObj.GetProperties();
                    foreach (PropertyInfo pro in properties)
                    {
                        foreach (var fromPro in fromProperties)
                        {
                            if (fromPro.Name.Equals(pro.Name, StringComparison.OrdinalIgnoreCase))
                            {
                                object value = fromPro.GetValue(fromEntity, null);
                                if (value != null && value != DBNull.Value)
                                {
                                    if (fromPro.PropertyType.Name != pro.PropertyType.Name)
                                    {
                                        if (pro.PropertyType.IsEnum)
                                        {
                                            pro.SetValue(t, Enum.Parse(pro.PropertyType, value.ToString()), null);
                                        }
                                        else
                                        {
                                            try
                                            {
                                                value = Convert.ChangeType
                                                (
                                                    value,
                                                    (Nullable.GetUnderlyingType(pro.PropertyType) ?? pro.PropertyType)
                                                );
                                                pro.SetValue(t, value, null);
                                            }
                                            catch { }
                                        }
                                    }
                                    else
                                    {
                                        pro.SetValue(t, value, null);
                                    }
                                }
                                else
                                {
                                    pro.SetValue(t, null, null);
                                }
                                break;
                            }
                        }
                    }
                }
                return t;
            }
    
            /// <summary>
            /// DataRow转换为实体类
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="dr"></param>
            /// <returns></returns>
            public static T ConvertToEntityByDataRow<T>(this DataRow dr) where T : new()
            {
                Type type = typeof(T);
                PropertyInfo[] properties = type.GetProperties();
                T t = new T();
                if (dr == null) return t;
                var columns = dr.Table.Columns.Cast<DataColumn>();
                foreach (PropertyInfo pi in properties)
                {
                    foreach (DataColumn column in dr.Table.Columns)
                    {
                        if (pi.Name.Equals(column.ColumnName, StringComparison.OrdinalIgnoreCase))
                        {
                            object value = dr[column];
                            if (value != null && value != DBNull.Value)
                            {
                                if (value.GetType().Name != pi.PropertyType.Name)
                                {
                                    if (pi.PropertyType.IsEnum)
                                    {
                                        pi.SetValue(t, Enum.Parse(pi.PropertyType, value.ToString()), null);
                                    }
                                    else
                                    {
                                        try
                                        {
                                            value = Convert.ChangeType
                                            (
                                                value,
                                                (Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType)
                                            );
                                            pi.SetValue(t, value, null);
                                        }
                                        catch { }
                                    }
                                }
                                else
                                {
                                    pi.SetValue(t, value, null);
                                }
                            }
                            else
                            {
                                pi.SetValue(t, null, null);
                            }
                            break;
                        }
                    }
                }
                return t;
            }
    
            /// <summary>
            /// 转换为DataTable,如果是集合没有数据行时候会抛异常。
            /// </summary>
            /// <param name="list"></param>
            /// <returns></returns>
            public static DataTable ConvertToDataTable(this object list)
            {
                if (list == null) return null;
                DataTable dt = new DataTable();
                if (list is IEnumerable)
                {
                    var li = (IList)list;
                    //li[0]代表的是一个对象,list没有行时,会抛异常。
                    PropertyInfo[] properties = li[0].GetType().GetProperties();
                    dt.Columns.AddRange(properties.Where(m => !m.PropertyType.IsClass || !m.PropertyType.IsInterface).Select(m =>
                        new DataColumn(m.Name, Nullable.GetUnderlyingType(m.PropertyType) ?? m.PropertyType)).ToArray());
                    foreach (var item in li)
                    {
                        DataRow dr = dt.NewRow();
                        foreach (PropertyInfo pp in properties.Where(m => m.PropertyType.GetProperty("Item") == null)) //过滤含有索引器的属性
                        {
                            object value = pp.GetValue(item, null);
                            dr[pp.Name] = value == null ? DBNull.Value : value;
                        }
                        dt.Rows.Add(dr);
                    }
                }
                else
                {
                    PropertyInfo[] properties = list.GetType().GetProperties();
                    properties = properties.Where(m => m.PropertyType.GetProperty("Item") == null).ToArray();//过滤含有索引器的属性
                    dt.Columns.AddRange(properties.Select(m =>
                        new DataColumn(m.Name, Nullable.GetUnderlyingType(m.PropertyType) ?? m.PropertyType)).ToArray());
                    DataRow dr = dt.NewRow();
                    foreach (PropertyInfo pp in properties)
                    {
                        object value = pp.GetValue(list, null);
                        dr[pp.Name] = value == null ? DBNull.Value : value;
                    }
                    dt.Rows.Add(dr);
                }
                return dt;
            }
    
    
            /// <summary>
            /// 转换为DataTable;如果list数据行为0,也不会抛异常,返回空行,是按照<T>进行转换。
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            /// <returns></returns>
            public static DataTable ConvertToDataTable<T>(this object list) where T : new()
            {
                var dt = new DataTable();
                if (list is IEnumerable)
                {
                    IEnumerable<T> collection = (IEnumerable<T>)list;
                    var props = typeof(T).GetProperties();
                    dt.Columns.AddRange(props.Select(p => new DataColumn(p.Name, p.PropertyType)).ToArray());
                    if (collection.Count() > 0)
                    {
                        for (int i = 0; i < collection.Count(); i++)
                        {
                            ArrayList tempList = new ArrayList();
                            foreach (PropertyInfo pi in props)
                            {
                                object obj = pi.GetValue(collection.ElementAt(i), null);
                                tempList.Add(obj);
                            }
                            object[] array = tempList.ToArray();
                            dt.LoadDataRow(array, true);
                        }
                    }
                }
                return dt;
            }
    
    
            /// <summary>
            /// 实体类公共属性值复制
            /// </summary>
            /// <param name="entity"></param>
            /// <param name="target"></param>
            public static void CopyTo(this object entity, object target)
            {
                if (target == null) return;
                if (entity.GetType() != target.GetType())
                    return;
                PropertyInfo[] properties = target.GetType().GetProperties();
                foreach (PropertyInfo pro in properties)
                {
                    if (pro.PropertyType.GetProperty("Item") != null)
                        continue;
                    object value = pro.GetValue(entity, null);
                    if (value != null)
                    {
                        if (value is ICloneable)
                        {
                            pro.SetValue(target, (value as ICloneable).Clone(), null);
                        }
                        else
                        {
                            pro.SetValue(target, value.Copy(), null);
                        }
                    }
                    else
                    {
                        pro.SetValue(target, null, null);
                    }
                }
            }
    
            public static object Copy(this object obj)
            {
                if (obj == null) return null;
                Object targetDeepCopyObj;
                Type targetType = obj.GetType();
                if (targetType.IsValueType == true)
                {
                    targetDeepCopyObj = obj;
                }
                else
                {
                    targetDeepCopyObj = System.Activator.CreateInstance(targetType);   //创建引用对象   
                    System.Reflection.MemberInfo[] memberCollection = obj.GetType().GetMembers();
    
                    foreach (System.Reflection.MemberInfo member in memberCollection)
                    {
                        if (member.GetType().GetProperty("Item") != null)
                            continue;
                        if (member.MemberType == System.Reflection.MemberTypes.Field)
                        {
                            System.Reflection.FieldInfo field = (System.Reflection.FieldInfo)member;
                            Object fieldValue = field.GetValue(obj);
                            if (fieldValue is ICloneable)
                            {
                                field.SetValue(targetDeepCopyObj, (fieldValue as ICloneable).Clone());
                            }
                            else
                            {
                                field.SetValue(targetDeepCopyObj, fieldValue.Copy());
                            }
                        }
                        else if (member.MemberType == System.Reflection.MemberTypes.Property)
                        {
                            System.Reflection.PropertyInfo myProperty = (System.Reflection.PropertyInfo)member;
                            MethodInfo info = myProperty.GetSetMethod(false);
                            if (info != null)
                            {
                                object propertyValue = myProperty.GetValue(obj, null);
                                if (propertyValue is ICloneable)
                                {
                                    myProperty.SetValue(targetDeepCopyObj, (propertyValue as ICloneable).Clone(), null);
                                }
                                else
                                {
                                    myProperty.SetValue(targetDeepCopyObj, propertyValue.Copy(), null);
                                }
                            }
                        }
                    }
                }
                return targetDeepCopyObj;
            }
    
            #endregion
    
            public static T ChangeType<T>(this object obj, T t)
            {
                return (T)obj;
            }
    
            public static string ConverToHTML(this DataTable dt)
            {
                System.Text.StringBuilder sb = new StringBuilder();
                sb.AppendLine("<table style='font-size:12px;' border='1' cellspacing='0' cellpadding='3'>");
                sb.Append("  <tr>");
                foreach (DataColumn col in dt.Columns)
                {
                    sb.Append(string.Format("<th>{0}</th>", col.ColumnName));
                }
                sb.AppendLine("  </tr>");
                foreach (DataRow dr in dt.Rows)
                {
                    sb.Append("  <tr>");
                    foreach (DataColumn col in dt.Columns)
                    {
                        sb.Append(string.Format("<td>{0}</td>", dr[col].ToString()));
                    }
                    sb.AppendLine("  </tr>");
                }
                sb.AppendLine("</table>");
                return sb.ToString();
            }
    
        }
    }
    
  • 相关阅读:
    7月25 SVN 提交报错 | mybatis like | 数据库字段设计 | 打包打小包
    7月24 springboot 打包打小包 | mybatis 逆向工程 | 接口返回数据 | 启动打包注意事项 | springboot redis 引入
    7月20号 添加字段报错 | 密码加密与传输
    7月19 登录失败 错误次数 | 字段类型被修改bug | 日志
    7月14 Enity对象的抽取
    7月13 mybatis调用存储过程
    7月12 导入项目到svn | logback配置日志输出
    7月11 配置数据库自己挖坑 | 代码覆盖率测试 | MockMvc 测试用例
    书架
    试题库问题
  • 原文地址:https://www.cnblogs.com/51net/p/3802033.html
Copyright © 2020-2023  润新知