/// <summary> /// 根据放入AutoModelFilterDict的字段(要指定排序功能)自动生成一个对应的ModelSorter用于Sort排序,若SortRuleDict中没有规则,则返回null /// </summary> /// <returns></returns> public Comparison <T> GetModelSorter() { if (ModelSortRuleDict.IsNullOrEmptySet()) { return(null); } return(delegate(T modelX, T modelY) { int result = 0; //1,-1,0分别是大,小,相等,默认升序 Dictionary <string, KeyValuePair <Type, object> > modelxInfoDict = ReflectionTool.GetAllPropertyInfo <T>(modelX); //获取一个model字段的信息 foreach (var modelProperty in modelxInfoDict) { string fieldName = modelProperty.Key; Type type = modelProperty.Value.Key; if (ModelSortRuleDict.TryGetValue(fieldName, out KeyValuePair <int, bool> rule) && typeof(IComparable).IsAssignableFrom(type)) //若该字段有排序规则且实现了Comparable接口 { var xValue = modelProperty.Value.Value; //原始字段值 var yValue = typeof(T).GetProperty(fieldName)?.GetValue(modelY); //要比较的字段值 int weight = rule.Key; //该字段排序权重 if (rule.Value) { weight = -weight; //若该字段是降序则权重相反 } weight *= ((IComparable)xValue).CompareTo(yValue); result += weight; } } return result; }); }
//Func<T, object, bool> func = (modelInstance, comparePair) => 的lamada表达式被简化为了本地函数 static bool func(T modelInstance, object comparePair) { bool result = true; Dictionary <string, KeyValuePair <object, FilterType> > list = (Dictionary <string, KeyValuePair <object, FilterType> >)comparePair;//[Key属性名 Value[Key属性值,Value过滤类型]] Dictionary <string, KeyValuePair <Type, object> > propertyInfoDict = ReflectionTool.GetAllPropertyInfo <T>(modelInstance); if (propertyInfoDict.IsNullOrEmptySet() || comparePair == null) { return(true); //没东西就不用过滤了 } foreach (var contrastPair in list) { var pair = contrastPair.Value; if (propertyInfoDict.TryGetValue(contrastPair.Key, out KeyValuePair <Type, object> originPair)) { Type propertyType = originPair.Key; object propertyValue = originPair.Value; object contrast = pair.Key; FilterType filterType = pair.Value; var origin = propertyValue;//原始字段值 //当Str类型支持Empty值时符合则匹配 if (filterType.HasFlag(FilterType.SupportStrEmpty) && contrast is string && origin is string && ((string)contrast).IsNullOrEmpty() && ((string)origin).IsNullOrEmpty()) { continue; } //原始值是空的不匹配,除非支持null值匹配 if (!filterType.HasFlag(FilterType.SupportNull) && origin == null) { return(false); } //原始值是值类型且是默认值的不匹配,除非支持默认值 if (origin is ValueType && !filterType.HasFlag(FilterType.SupportValueDefault) && origin.Equals(Activator.CreateInstance(propertyType))) { return(false); } //比较值为空的匹配,因为没有做限制,除非支持null认为null也是限制 if (!filterType.HasFlag(FilterType.SupportNull) && contrast == null) { continue; } //当仅过滤空值、默认值时直接匹配(因为前面已经过滤掉了) if (filterType.HasFlag(FilterType.OnlyFilterNull)) { continue; } if (origin is string) //类型是string的 { string ori = (string)origin; if (ori == string.Empty && !filterType.HasFlag(FilterType.SupportStrEmpty)) { return(false); } string con = (string)contrast; switch (filterType) { case var _ when filterType.HasFlag(FilterType.Exact): //C#7.0特性 case的when约束,要true才会成功case case FilterType.Exact: result &= ori.Equals(con); break; case FilterType.IgnoreCase: result &= ori.Equals(con, StringComparison.OrdinalIgnoreCase); break; case FilterType.Fuzzy: result &= ori.Trim().Contains(con.Trim()); break; case FilterType.FuzzyIgnoreCase: result &= ori.ToLower().Trim().Contains(con.ToLower().Trim()); break; case FilterType.Interval: //转为闭区间类型 result &= ori.TryGetInterval(out double left, out double right, true) && con.TryGetInterval(out double conleft, out double conright, true) && (conleft <= left && right <= conright); break; default: goto case FilterType.FuzzyIgnoreCase; } } else if (origin is double || origin is int && contrast is string)//数值型支持区间表示 { double ori = System.Convert.ToDouble(origin); string con = (string)contrast; if (ZhNumber.IsContainZhNumber(con)) { con = ZhNumber.ToArabicNumber(con); } if (double.TryParse(con, out double num))//直接精确等于 { result &= num == ori; } else if (con.TryGetInterval(out IntervalDouble left, out IntervalDouble right))//区间表示 { if (!(ori >= left && ori <= right)) { return(false); } } else { return(false);//无法转换则不匹配 } } else if (origin is Enum)//支持枚举类过滤 { if (contrast is string con) { result &= Enum.Parse(propertyType, con).Equals(origin); } else { result &= contrast.Equals(origin); } } else if (origin is TimeSpan span && contrast is string con)//支持TimeSpan区间型过滤 { if (con.TryGetTimeSpan(out TimeSpan timeSpan)) { if (timeSpan != span) { return(false); } } else if (con.TryGetTimeSpanInterval(out TimeSpan left, out TimeSpan right)) { if (!(span >= left && span <= right)) { return(false); //不在区间内 } } else//尝试古代时间、现代时间以及中文计数法 { var interval = Regex.Split(con, "(到|[-~,])+"); string rightCon = "";//尝试是否存在第二个以构成区间 bool isRightExist = false; if (interval.Length >= 3) { con = interval[0]; rightCon = interval[2]; isRightExist = true; } TimeSpan zhTimeSpan = new TimeSpan(); bool success = KouStringTool.TryToTimeSpan(con, out zhTimeSpan); if (success && isRightExist)//如果左边成功了尝试是否有第二个构成区间 { TimeSpan zhTimeSpanRight = new TimeSpan(); bool successRight = KouStringTool.TryToTimeSpan(rightCon, out zhTimeSpanRight); if (!successRight || zhTimeSpan > zhTimeSpanRight || span < zhTimeSpan || span > zhTimeSpanRight) { return(false); //原时间间隔不在区间内的不匹配 } } else if (!success || zhTimeSpan != span) { return(false); //时间与原时间间隔的不一致的不匹配 } } } else//其他类型直接比较是否相等 { contrast = System.Convert.ChangeType(contrast, propertyType); result &= contrast.Equals(origin); } if (result == false) { return(false); } } }