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