using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq.Expressions; namespace Guma.StudyNotes.ExpressionExtend.Utils { /// <summary> /// 表达式通用映射器 /// </summary> /// <remarks>@Auth: Guma;@Website: www.1995v.com</remarks> /// <typeparam name="TIn">传入类型:不能为集合类型,会引发 ParameterCannotCollectionException 异常</typeparam> /// <typeparam name="TOut">返回类型:不能为集合类型,会引发 ParameterCannotCollectionException 异常</typeparam> public static class ExpressionGenericMapper<TIn, TOut> where TIn : class, new() where TOut : class, new() { private static Func<TIn, TOut> _func = null; static ExpressionGenericMapper() { if (typeof(TIn).Namespace.Contains("System.Collections")) { throw new ParameterCannotCollectionException(); } else { ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p"); List<MemberBinding> memberBindingList = new List<MemberBinding>(); foreach (var item in typeof(TOut).GetProperties()) { if (item.SetMethod != null) { MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } } foreach (var item in typeof(TOut).GetFields()) { MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name)); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray()); Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression }); _func = lambda.Compile(); } } #region Overloading Methods public static TOut Trans(TIn t) { return _func(t); } public static List<TOut> Trans(List<TIn> t) { List<TOut> lstTout = new List<TOut>(); foreach (var item in t) { lstTout.Add(_func(item)); } return lstTout; } public static Dictionary<T, TOut> Trans<T>(Dictionary<T, TIn> t) { Dictionary<T, TOut> mapTout = new Dictionary<T, TOut>(); foreach (var item in t) { mapTout.Add(item.Key, _func(item.Value)); } return mapTout; } public static Stack<TOut> Trans(Stack<TIn> t) { Stack<TOut> stackout = new Stack<TOut>(); foreach (var item in t) { stackout.Push(_func(item)); } return stackout; } public static Queue<TOut> Trans(Queue<TIn> t) { Queue<TOut> queuekout = new Queue<TOut>(); foreach (var item in t) { queuekout.Enqueue(_func(item)); } return queuekout; } public static ConcurrentBag<TOut> Trans(ConcurrentBag<TIn> t) { ConcurrentBag<TOut> bagout = new ConcurrentBag<TOut>(); foreach (var item in t) { bagout.Add(_func(item)); } return bagout; } public static ConcurrentDictionary<T, TOut> Trans<T>(ConcurrentDictionary<T, TIn> t) { ConcurrentDictionary<T, TOut> mapout = new ConcurrentDictionary<T, TOut>(); foreach (var item in t) { mapout.TryAdd(item.Key, _func(item.Value)); } return mapout; } public static ConcurrentQueue<TOut> Trans(ConcurrentQueue<TIn> t) { ConcurrentQueue<TOut> queueout = new ConcurrentQueue<TOut>(); foreach (var item in t) { queueout.Enqueue(_func(item)); } return queueout; } public static ConcurrentStack<TOut> Trans(ConcurrentStack<TIn> t) { ConcurrentStack<TOut> stackout = new ConcurrentStack<TOut>(); foreach (var item in t) { stackout.Push(_func(item)); } return stackout; } #endregion #region ExceptionList class ParameterCannotCollectionException : ApplicationException { private const string _message = "当前泛型不能为集合类型,请使用集合方式的重载方法"; public ParameterCannotCollectionException(string message = _message) : base(message) { } } #endregion } }