using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Expressions; using System.Reflection; using WalkingTec.Mvvm.Core.Extensions; namespace WalkingTec.Mvvm.Core { /// /// 重复数据组 /// /// 重复数据类 public class DuplicatedGroup { public List> Fields { get; set; } } /// /// 重复数据信息 /// /// 数据类 public class DuplicatedInfo { //重复数据分组 public List> Groups { get; set; } public DuplicatedInfo() { Groups = new List>(); } /// /// 添加一组重复信息,一组中的多个字段必须同时重复才认为是重复数据 /// /// 一个或多个重复数据字段 public DuplicatedInfo AddGroup(params DuplicatedField[] FieldExps) { DuplicatedGroup newGroup = new DuplicatedGroup() { Fields = new List>() }; foreach (var exp in FieldExps) { newGroup.Fields.Add(exp); } Groups.Add(newGroup); return this; } } /// /// 简单重复数据字段信息 /// /// 重复数据类 public class DuplicatedField { //直接可顺序关联出的字段 protected Expression> _directFieldExp { get; set; } public virtual List GetProperties() { List rv = new List { PropertyHelper.GetPropertyInfo(_directFieldExp) }; return rv; } /// /// 根据设定的字段,生成查询重复数据的Lambda,最终返回类似 x=>x.property == val的lambda /// /// 要验证字段的实体类 /// ParameterExpression /// public virtual Expression GetExpression(T Entity, ParameterExpression para) { var propName = PropertyHelper.GetPropertyName(_directFieldExp); var prop = PropertyHelper.GetPropertyInfo(_directFieldExp); var func = _directFieldExp.Compile(); var val = func.Invoke(Entity); ////如果字段值为null则跳过,因为一般情况下null值不会被认为重复 //if (val == null) //{ // return res; //} //如果字段值是空字符串,则跳过 if (val is string && val.ToString() == string.Empty) { var requiredAttrs = prop.GetCustomAttributes(typeof(RequiredAttribute), false).ToList(); if (requiredAttrs == null || requiredAttrs.Count == 0) { return null; } else { var requiredAtt = requiredAttrs[0] as RequiredAttribute; if (requiredAtt.AllowEmptyStrings == true) { return null; } } } //生成一个表达式,类似于 x=>x.field == val var splits = propName.Split('.'); var idproperty = typeof(T).GetSingleProperty(splits[0]); Expression left = Expression.Property(para, idproperty); for (int i = 1; i < splits.Length; i++) { var tempproperty = typeof(T).GetSingleProperty(splits[i]); left = Expression.Property(left, tempproperty); } if (val != null && left.Type.IsGeneric(typeof(Nullable<>))) { left = Expression.Property(left, "Value"); } if (left.Type == typeof(string)) { left = Expression.Call(left, typeof(String).GetMethod("Trim", Type.EmptyTypes)); } if (val is string) { val = val.ToString().Trim(); } var right = Expression.Constant(val); var equal = Expression.Equal(left, right); return equal; } protected DuplicatedField() { } /// /// 创建一个包含可顺序关联出字段的简单重复字段信息 /// /// 字段 /// 字段信息 public DuplicatedField(Expression> FieldExp) { _directFieldExp = FieldExp; } } /// /// 复杂重复字段信息接口 /// public interface IComplexDuplicatedField { Type GetMiddleTableType(); } /// /// 复杂重复数据字段信息 /// /// 重复数据类 /// 重复数据关联的List中的类 public class ComplexDuplicatedField : DuplicatedField, IComplexDuplicatedField { /// /// 中间字段 /// private Expression>> _middleExp { get; set; } /// /// 最终字段 /// private List>> _subFieldExps { get; set; } protected ComplexDuplicatedField() { } /// /// 创建一个复杂字段 /// /// 中间字段类 /// 最终字段类 /// public ComplexDuplicatedField(Expression>> MiddleExp, params Expression>[] FieldExps) { _middleExp = MiddleExp; _subFieldExps = new List>>(); _subFieldExps.AddRange(FieldExps); } public Type GetMiddleTableType() { return typeof(V); } /// /// 生成验证复杂字段是否重复的Lambda /// /// 源数据 /// 源数据类型 /// Where语句 public override Expression GetExpression(T Entity, ParameterExpression para) { ParameterExpression midPara = Expression.Parameter(typeof(V), "tm2"); //获取中间表的List var list = _middleExp.Compile().Invoke(Entity); if (list == null) { return null; } List allExp = new List(); Expression rv = null; //循环中间表数据 foreach (var li in list) { List innerExp = new List(); bool needBreak = false; //循环中间表要检查重复的字段 foreach (var SubFieldExp in _subFieldExps) { //拼接字段表达式,使left等于类似 x.field 的形式 Expression left = Expression.Property(midPara, SubFieldExp.GetPropertyName()); //如果字段是nullable类型的,则拼接value,形成类似 x.field.Value的形式 if (left.Type.IsGeneric(typeof(Nullable<>)) == true) { left = Expression.Property(left, "Value"); } //如果字段是string类型,则拼接trim,形成类似 x.field.Trim()的形式 if (left.Type == typeof(string)) { left = Expression.Call(left, typeof(String).GetMethod("Trim", Type.EmptyTypes)); } //使用当前循环的中间表的数据获取字段的值 object vv = SubFieldExp.Compile().Invoke(li); //如果值为空则跳过 if (vv == null) { needBreak = true; continue; } //如果值为空字符串且没要求必填,则跳过 if (vv is string && vv.ToString() == "") { var requiredAttrs = li.GetType().GetSingleProperty(SubFieldExp.GetPropertyName()).GetCustomAttributes(typeof(RequiredAttribute), false).ToList(); if (requiredAttrs == null || requiredAttrs.Count == 0) { needBreak = true; continue; } else { var requiredAtt = requiredAttrs[0] as RequiredAttribute; if (requiredAtt.AllowEmptyStrings == true) { needBreak = true; continue; } } } //如果值为字符串,调用trim函数 if (vv is string) { vv = vv.ToString().Trim(); } //拼接形成 x.field == value的形式 ConstantExpression right = Expression.Constant(vv); BinaryExpression equal = Expression.Equal(left, right); innerExp.Add(equal); } if (needBreak) { continue; } //拼接多个 x.field==value,形成 x.field==value && x.field1==value1 .....的形式 Expression exp = null; if (innerExp.Count == 1) { exp = innerExp[0]; } if (innerExp.Count > 1) { exp = Expression.And(innerExp[0], innerExp[1]); for (int i = 2; i < innerExp.Count; i++) { exp = Expression.And(exp, innerExp[i]); } } //调用any函数,形成 .Any(x=> x.field==value && x.field1==value1....)的形式 if (exp != null) { var any = Expression.Call( typeof(Enumerable), "Any", new Type[] { typeof(V) }, Expression.Property(para, _middleExp.GetPropertyName()), Expression.Lambda>(exp, new ParameterExpression[] { midPara })); allExp.Add(any); } } //拼接多个any函数形成 .Any(x=> x.field==value && x.field1==value1....) || .Any(x=> x.field==value && x.field1==value1....)的形式并返回 if (allExp.Count == 1) { rv = allExp[0]; } if (allExp.Count > 1) { rv = Expression.OrElse(allExp[0], allExp[1]); for (int i = 2; i < allExp.Count; i++) { rv = Expression.OrElse(rv, allExp[i]); } } return rv; } /// /// 获取字段属性 /// /// 字段属性列表 public override List GetProperties() { List rv = new List(); foreach (var subField in _subFieldExps) { var pro = subField.GetPropertyInfo(); if (pro != null) { rv.Add(pro); } } return rv; } } }