using SqlSugar; 
 | 
using System; 
 | 
using System.Collections.Generic; 
 | 
using System.ComponentModel.DataAnnotations; 
 | 
using System.ComponentModel.DataAnnotations.Schema; 
 | 
using System.Linq; 
 | 
using System.Reflection; 
 | 
using System.Text; 
 | 
using System.Threading.Tasks; 
 | 
using WIDESEA_Core.Const; 
 | 
using WIDESEA_Core.DB.Models; 
 | 
using WIDESEA_Core.Helper; 
 | 
  
 | 
namespace WIDESEA_Core.Utilities 
 | 
{ 
 | 
    public static class EntityProperties 
 | 
    { 
 | 
        /// <summary> 
 | 
        /// 验证数据库字段类型与值是否正确, 
 | 
        /// </summary> 
 | 
        /// <param name="dbType">数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50))</param> 
 | 
        /// <param name="value">值</param> 
 | 
        /// <param name="propertyInfo">要验证的类的属性,若不为null,则会判断字符串的长度是否正确</param> 
 | 
        /// <returns>(bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值</returns> 
 | 
        public static (bool, string, object) ValidationVal(this PropertyInfo propertyInfo, object value) 
 | 
        { 
 | 
            string dbType = ""; 
 | 
            SugarColumn sugarColumn = null; 
 | 
            if (propertyInfo != null) 
 | 
            { 
 | 
                sugarColumn = propertyInfo.GetCustomAttribute<SugarColumn>(); 
 | 
                dbType = propertyInfo != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar; 
 | 
            } 
 | 
            dbType = dbType.ToLower(); 
 | 
            string val = value?.ToString(); 
 | 
            //验证长度 
 | 
            string reslutMsg = string.Empty; 
 | 
            if (dbType == SqlDbTypeName.Int) 
 | 
            { 
 | 
                if (!value.IsInt()) 
 | 
                    reslutMsg = "只能为有效整数"; 
 | 
            }  //2021.10.12增加属性校验long类型的支持 
 | 
            else if (dbType == SqlDbTypeName.BigInt) 
 | 
            { 
 | 
                if (!long.TryParse(val, out _)) 
 | 
                { 
 | 
                    reslutMsg = "只能为有效整数"; 
 | 
                } 
 | 
            } 
 | 
            else if (dbType == SqlDbTypeName.DateTime 
 | 
                || dbType == SqlDbTypeName.Date 
 | 
                || dbType == SqlDbTypeName.SmallDateTime 
 | 
                || dbType == SqlDbTypeName.SmallDate 
 | 
                ) 
 | 
            { 
 | 
                if (!value.IsDate()) 
 | 
                    reslutMsg = "必须为日期格式"; 
 | 
            } 
 | 
            else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double) 
 | 
            { 
 | 
                if (!val.IsNumber(null)) 
 | 
                { 
 | 
                    reslutMsg = "不是有效数字"; 
 | 
                } 
 | 
            } 
 | 
            else if (dbType == SqlDbTypeName.UniqueIdentifier) 
 | 
            { 
 | 
                if (!val.IsGuid()) 
 | 
                { 
 | 
                    reslutMsg = propertyInfo.Name + "Guid不正确"; 
 | 
                } 
 | 
            } 
 | 
            else if (propertyInfo != null 
 | 
                && (dbType == SqlDbTypeName.VarChar 
 | 
                || dbType == SqlDbTypeName.NVarChar 
 | 
                || dbType == SqlDbTypeName.NChar 
 | 
                || dbType == SqlDbTypeName.Char 
 | 
                || dbType == SqlDbTypeName.Text)) 
 | 
            { 
 | 
                //默认nvarchar(max) 、text 长度不能超过20000 
 | 
                if (val.Length > 200000) 
 | 
                { 
 | 
                    reslutMsg = $"字符长度最多【200000】"; 
 | 
                } 
 | 
                else 
 | 
                { 
 | 
                    int length = sugarColumn.Length; 
 | 
                    if (length == 0) { return (true, null, null); } 
 | 
                    //判断双字节与单字段 
 | 
                    else if (length < 8000 && 
 | 
                        ((dbType.Substring(0, 1) != "n" 
 | 
                        && Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length) 
 | 
                         || val.Length > length) 
 | 
                         ) 
 | 
                    { 
 | 
                        reslutMsg = $"最多只能【{length}】个字符。"; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
            if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null) 
 | 
            { 
 | 
                reslutMsg = sugarColumn.ColumnDescription + reslutMsg; 
 | 
            } 
 | 
            return (reslutMsg == "" ? true : false, reslutMsg, value); 
 | 
        } 
 | 
  
 | 
        private static readonly Dictionary<Type, string> ProperWithDbType = new Dictionary<Type, string>() { 
 | 
            {  typeof(string),SqlDbTypeName.NVarChar }, 
 | 
            { typeof(DateTime),SqlDbTypeName.DateTime}, 
 | 
            {typeof(long),SqlDbTypeName.BigInt }, 
 | 
            {typeof(int),SqlDbTypeName.Int}, 
 | 
            { typeof(decimal),SqlDbTypeName.Decimal }, 
 | 
            { typeof(float),SqlDbTypeName.Float }, 
 | 
            { typeof(double),SqlDbTypeName.Double }, 
 | 
            {  typeof(byte),SqlDbTypeName.Int },//类型待完 
 | 
            { typeof(Guid),SqlDbTypeName.UniqueIdentifier} 
 | 
        }; 
 | 
  
 | 
        public static string GetProperWithDbType(this PropertyInfo propertyInfo) 
 | 
        { 
 | 
            bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value); 
 | 
            if (result) 
 | 
            { 
 | 
                return value; 
 | 
            } 
 | 
            return SqlDbTypeName.NVarChar; 
 | 
        } 
 | 
  
 | 
        public static string ValidateDicInEntity(this Type typeinfo, List<Dictionary<string, object>> dicList, bool removerKey, string[] ignoreFields = null) 
 | 
        { 
 | 
            PropertyInfo[] propertyInfo = typeinfo.GetProperties(); 
 | 
            string reslutMsg = string.Empty; 
 | 
            foreach (Dictionary<string, object> dic in dicList) 
 | 
            { 
 | 
                reslutMsg = typeinfo.ValidateDicInEntity(dic, removerKey, propertyInfo, ignoreFields); 
 | 
                if (!string.IsNullOrEmpty(reslutMsg)) 
 | 
                    return reslutMsg; 
 | 
            } 
 | 
            return reslutMsg; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// 判断hash的列是否为对应的实体,并且值是否有效 
 | 
        /// </summary> 
 | 
        /// <param name="typeinfo"></param> 
 | 
        /// <param name="dic"></param> 
 | 
        /// <param name="removeNotContains">移除不存在字段</param> 
 | 
        /// <param name="removerKey">移除主键</param> 
 | 
        /// <returns></returns> 
 | 
        public static string ValidateDicInEntity(this Type typeinfo, Dictionary<string, object> dic, bool removerKey, PropertyInfo[] propertyInfo, string[] ignoreFields = null) 
 | 
        { 
 | 
            if (dic == null || dic.Count == 0) { return "参数无效"; } 
 | 
  
 | 
            // 不存在的字段直接移除 
 | 
            dic.Where(x => !propertyInfo.Any(p => p.Name == x.Key.FirstLetterToUpper())).Select(s => s.Key).ToList().ForEach(f => 
 | 
            { 
 | 
                dic.Remove(f); 
 | 
            }); 
 | 
  
 | 
            string keyName = typeinfo.GetKeyName(); 
 | 
            //移除主键 
 | 
            if (removerKey) 
 | 
                dic.Remove(keyName); 
 | 
            //else 
 | 
            //{ 
 | 
            //    if (!dic.ContainsKey(keyName)) 
 | 
            //        return "请传入主键参数"; 
 | 
            //} 
 | 
  
 | 
            foreach (PropertyInfo property in propertyInfo) 
 | 
            { 
 | 
                SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); 
 | 
                if (sugarColumn == null) 
 | 
                    return "请配置SugarColumn属性"; 
 | 
                //忽略与主键的字段不做验证 
 | 
                if (property.Name == keyName.FirstLetterToUpper() || (ignoreFields != null && ignoreFields.Contains(property.Name)) || sugarColumn.IsOnlyIgnoreInsert || sugarColumn.IsOnlyIgnoreUpdate || sugarColumn.IsIgnore) 
 | 
                    continue; 
 | 
  
 | 
                //不在编辑中的列,是否也要必填 
 | 
                if (!dic.ContainsKey(property.Name.FirstLetterToLower())) 
 | 
                { 
 | 
                    if (!sugarColumn.IsNullable) 
 | 
                    { 
 | 
                        if (sugarColumn.DefaultValue != null) 
 | 
                            return sugarColumn.ColumnDescription + "为必须提交项"; 
 | 
                        continue; 
 | 
                    } 
 | 
                    continue; 
 | 
                } 
 | 
                string str = dic.GetValueOrDefault(property.Name.FirstLetterToLower(), "").ToString(); 
 | 
                //将所有空值设置为null 
 | 
                if (dic[property.Name.FirstLetterToLower()] != null && str == string.Empty) 
 | 
                    dic[property.Name.FirstLetterToLower()] = null; 
 | 
            } 
 | 
            return string.Empty; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// 安全获取字典值,如果键不存在或值为null则返回默认值 
 | 
        /// </summary> 
 | 
        /// <typeparam name="TKey">字典键的类型</typeparam> 
 | 
        /// <typeparam name="TValue">字典值的类型</typeparam> 
 | 
        /// <param name="dictionary">字典实例</param> 
 | 
        /// <param name="key">键</param> 
 | 
        /// <param name="defaultValue">默认值</param> 
 | 
        /// <returns>字典值或默认值</returns> 
 | 
        public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default) 
 | 
        { 
 | 
            if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); 
 | 
  
 | 
            return dictionary.TryGetValue(key, out TValue value) && value != null ? value : defaultValue; 
 | 
        } 
 | 
  
 | 
        public static string GetKeyName(this Type typeinfo) 
 | 
        { 
 | 
            return typeinfo.GetProperties().GetKeyName(); 
 | 
        } 
 | 
  
 | 
        public static string GetKeyName(this PropertyInfo[] properties) 
 | 
        { 
 | 
            foreach (PropertyInfo property in properties) 
 | 
            { 
 | 
                SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); 
 | 
                if (sugarColumn.IsPrimaryKey) 
 | 
                    return property.Name; 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
  
 | 
        public static PropertyInfo GetKeyProperty(this Type typeinfo) 
 | 
        { 
 | 
            PropertyInfo[] properties = typeinfo.GetProperties(); 
 | 
            foreach (PropertyInfo property in properties) 
 | 
            { 
 | 
                SugarColumn sugarColumn = property.GetCustomAttribute<SugarColumn>(); 
 | 
                if (sugarColumn?.IsPrimaryKey ?? false) 
 | 
                { 
 | 
                    return property; 
 | 
                } 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
  
 | 
        public static Type GetDetailType(this Type typeinfo) 
 | 
        { 
 | 
            PropertyInfo[] properties = typeinfo.GetProperties(); 
 | 
            foreach (PropertyInfo property in properties) 
 | 
            { 
 | 
                Navigate? navigate = property.GetCustomAttribute<Navigate>(); 
 | 
                if (navigate is not null) 
 | 
                { 
 | 
                    if (navigate.GetNavigateType() == NavigateType.OneToOne) 
 | 
                        return property.PropertyType; 
 | 
                    else 
 | 
                        return property.PropertyType.GenericTypeArguments[0]; 
 | 
                } 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
  
 | 
        public static string GetMainIdByDetail(this Type typeinfo) 
 | 
        { 
 | 
            PropertyInfo[] properties = typeinfo.GetProperties(); 
 | 
            foreach (PropertyInfo property in properties) 
 | 
            { 
 | 
                Navigate? navigate = property.GetCustomAttribute<Navigate>(); 
 | 
                if (navigate is not null) 
 | 
                { 
 | 
                    return navigate.GetName(); 
 | 
                } 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
  
 | 
        public static void SetDetailId<T>(this Type typeinfo, T enetiy, object id, string name) 
 | 
        { 
 | 
            PropertyInfo property = typeinfo.GetProperty(name); 
 | 
            if (property != null) 
 | 
            { 
 | 
                property.SetValue(enetiy, id); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        public static PropertyInfo? GetNavigatePro(this Type typeinfo) 
 | 
        { 
 | 
            PropertyInfo[] properties = typeinfo.GetProperties(); 
 | 
            foreach (PropertyInfo property in properties) 
 | 
            { 
 | 
                Navigate? navigate = property.GetCustomAttribute<Navigate>(); 
 | 
                if (navigate is not null) 
 | 
                { 
 | 
                    return property; 
 | 
                } 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
  
 | 
        public static object GetPropertyValue<T>(this Type typeinfo, T data, string propertyName) 
 | 
        { 
 | 
            if (typeinfo != typeof(T)) 
 | 
                return null; 
 | 
  
 | 
            PropertyInfo? property = typeinfo.GetProperty(propertyName); 
 | 
            if (property != null) 
 | 
            { 
 | 
                return property.GetValue(data); 
 | 
            } 
 | 
            return null; 
 | 
        } 
 | 
    } 
 | 
} 
 |