You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Reflection;
using AutoMapper;
namespace DSWeb.Areas.MvcShipping.Helper
{
/// <summary>
/// AutoMapper的帮助类
/// </summary>
public static class AutoMapperHelper
{
/// <summary>
/// 来源,目标
/// 单条实体类型映射,默认字段名字一一对应
///
/// </summary>
/// <typeparam name="TSource">Dto类型</typeparam>
/// <typeparam name="TDestination">要被转化的数据</typeparam>
/// <param name="source">转化之后的实体</param>
/// <returns></returns>
public static TDestination MapTo<TSource, TDestination>(this TSource source)
where TDestination : class, new()
where TSource : class
{
if (source == null) return new TDestination();
var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
var mapper = config.CreateMapper();
return mapper.Map<TDestination>(source);
}
/// <summary>
/// 实体列表类型映射,默认字段名字一一对应
/// </summary>
/// <typeparam name="TDestination">Dto类型</typeparam>
/// <typeparam name="TSource">要被转化的数据</typeparam>
/// <param name="source">可以使用这个扩展方法的类型,任何引用类型</param>
/// <returns>转化之后的实体列表</returns>
public static List<TDestination> MapToList<TSource, TDestination>(this IEnumerable<TSource> source)
where TDestination : class
where TSource : class
{
if (source == null) return new List<TDestination>();
var config = new MapperConfiguration(cfg => cfg.CreateMap<TSource, TDestination>());
var mapper = config.CreateMapper();
return mapper.Map<List<TDestination>>(source);
}
}
/// <summary>
///
/// </summary>
public class Query
{
public enum Operators
{
None = 0,
Equal = 1,
GreaterThan = 2,
GreaterThanOrEqual = 3,
LessThan = 4,
LessThanOrEqual = 5,
Contains = 6,
StartWith = 7,
EndWidth = 8,
Range = 9
}
public enum Condition
{
OrElse = 1,
AndAlso = 2
}
public string Name { get; set; }
public Operators Operator { get; set; }
public object Value { get; set; }
public object ValueMin { get; set; }
public object ValueMax { get; set; }
}
/// <summary>
/// 动态拼接lamba子句
/// 典型调用方式:
/// //找到所有需要盘点的库存
/// List<VW_OP_WMS_AREAGOODS> 符合条件的在库库存 = new List<VW_OP_WMS_AREAGOODS>();
/// QueryCollection queries = new QueryCollection();
/// if(!string.IsNullOrWhiteSpace(head.CUSTOMERNAME))
/// queries.Add(new Query { Name = "CUSTOMERNAME", Operator = Query.Operators.Equal, Value = head.CUSTOMERNAME
/// });
///if (!string.IsNullOrWhiteSpace(head.STOREHOUSE))
/// queries.Add(new Query { Name = "STOREHOUSE", Operator = Query.Operators.Equal, Value = head.STOREHOUSE });
///if (!string.IsNullOrWhiteSpace(head.GOODSOWNER))
/// queries.Add(new Query { Name = "GOODSOWNER", Operator = Query.Operators.Equal, Value = head.GOODSOWNER });
///if (!string.IsNullOrWhiteSpace(head.AREACODE))
/// queries.Add(new Query { Name = "AREACODE", Operator = Query.Operators.StartWith, Value = head.AREACODE });
///符合条件的在库库存 = VW_OP_WMS_AREAGOODSRepository.Instance.FindAsIQueryable(queries.AsExpression<VW_OP_WMS_AREAGOODS>(Query.Condition.AndAlso)).ToList();
/// </summary>
public class QueryCollection : Collection<Query>
{
public Expression<Func<T, bool>> AsExpression<T>(Query.Condition? condition = Query.Condition.OrElse) where T : class
{
Type targetType = typeof(T);
TypeInfo typeInfo = targetType.GetTypeInfo();
var parameter = Expression.Parameter(targetType, "m");
Expression expression = null;
Func<Expression, Expression, Expression> Append = (exp1, exp2) =>
{
if (exp1 == null)
{
return exp2;
}
return (condition ?? Query.Condition.OrElse) == Query.Condition.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2);
};
foreach (var item in this)
{
var property = typeInfo.GetProperty(item.Name);
if (property == null ||
!property.CanRead ||
(item.Operator != Query.Operators.Range && item.Value == null) ||
(item.Operator == Query.Operators.Range && item.ValueMin == null && item.ValueMax == null))
{
continue;
}
Type realType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
if (item.Value != null)
{
item.Value = Convert.ChangeType(item.Value, realType);
}
Expression<Func<object>> valueLamba = () => item.Value;
switch (item.Operator)
{
case Query.Operators.Equal:
{
expression = Append(expression, Expression.Equal(Expression.Property(parameter, item.Name),
Expression.Convert(valueLamba.Body, property.PropertyType)));
break;
}
case Query.Operators.GreaterThan:
{
expression = Append(expression, Expression.GreaterThan(Expression.Property(parameter, item.Name),
Expression.Convert(valueLamba.Body, property.PropertyType)));
break;
}
case Query.Operators.GreaterThanOrEqual:
{
expression = Append(expression, Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name),
Expression.Convert(valueLamba.Body, property.PropertyType)));
break;
}
case Query.Operators.LessThan:
{
expression = Append(expression, Expression.LessThan(Expression.Property(parameter, item.Name),
Expression.Convert(valueLamba.Body, property.PropertyType)));
break;
}
case Query.Operators.LessThanOrEqual:
{
expression = Append(expression, Expression.LessThanOrEqual(Expression.Property(parameter, item.Name),
Expression.Convert(valueLamba.Body, property.PropertyType)));
break;
}
case Query.Operators.Contains:
{
var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
var contains = Expression.Call(Expression.Property(parameter, item.Name), "Contains", null,
Expression.Convert(valueLamba.Body, property.PropertyType));
expression = Append(expression, Expression.AndAlso(nullCheck, contains));
break;
}
case Query.Operators.StartWith:
{
var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
var startsWith = Expression.Call(Expression.Property(parameter, item.Name), "StartsWith", null,
Expression.Convert(valueLamba.Body, property.PropertyType));
expression = Append(expression, Expression.AndAlso(nullCheck, startsWith));
break;
}
case Query.Operators.EndWidth:
{
var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, Expression.Property(parameter, item.Name)));
var endsWith = Expression.Call(Expression.Property(parameter, item.Name), "EndsWith", null,
Expression.Convert(valueLamba.Body, property.PropertyType));
expression = Append(expression, Expression.AndAlso(nullCheck, endsWith));
break;
}
case Query.Operators.Range:
{
Expression minExp = null, maxExp = null;
if (item.ValueMin != null)
{
var minValue = Convert.ChangeType(item.ValueMin, realType);
Expression<Func<object>> minValueLamda = () => minValue;
minExp = Expression.GreaterThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(minValueLamda.Body, property.PropertyType));
}
if (item.ValueMax != null)
{
var maxValue = Convert.ChangeType(item.ValueMax, realType);
Expression<Func<object>> maxValueLamda = () => maxValue;
maxExp = Expression.LessThanOrEqual(Expression.Property(parameter, item.Name), Expression.Convert(maxValueLamda.Body, property.PropertyType));
}
if (minExp != null && maxExp != null)
{
expression = Append(expression, Expression.AndAlso(minExp, maxExp));
}
else if (minExp != null)
{
expression = Append(expression, minExp);
}
else if (maxExp != null)
{
expression = Append(expression, maxExp);
}
break;
}
}
}
if (expression == null)
{
return null;
}
return ((Expression<Func<T, bool>>)Expression.Lambda(expression, parameter));
}
}
}