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;
}
}
}