浏览代码

重构表达式树对象映射器mapper,已支持可配置化。

懒得勤快 6 年之前
父节点
当前提交
f1e36e9928
共有 25 个文件被更改,包括 2433 次插入0 次删除
  1. 70 0
      Masuit.Tools.Core/Mapping/Copier.cs
  2. 12 0
      Masuit.Tools.Core/Mapping/Core/CreateConfig.cs
  3. 193 0
      Masuit.Tools.Core/Mapping/Core/MapperConfiguration.cs
  4. 667 0
      Masuit.Tools.Core/Mapping/Core/MapperConfigurationBase.cs
  5. 108 0
      Masuit.Tools.Core/Mapping/Core/MapperConfigurationCollectionContainer.cs
  6. 35 0
      Masuit.Tools.Core/Mapping/Core/PropertiesNotMapped.cs
  7. 59 0
      Masuit.Tools.Core/Mapping/Core/TypePairMapper.cs
  8. 56 0
      Masuit.Tools.Core/Mapping/Exceptions/MapperExceptionBase.cs
  9. 55 0
      Masuit.Tools.Core/Mapping/Exceptions/MapperExistException.cs
  10. 54 0
      Masuit.Tools.Core/Mapping/Exceptions/MapperNotInitializedException.cs
  11. 46 0
      Masuit.Tools.Core/Mapping/Exceptions/NoActionAfterMappingException.cs
  12. 54 0
      Masuit.Tools.Core/Mapping/Exceptions/NoFoundMapperException.cs
  13. 53 0
      Masuit.Tools.Core/Mapping/Exceptions/NotSameTypePropertyException.cs
  14. 54 0
      Masuit.Tools.Core/Mapping/Exceptions/PropertyNoExistException.cs
  15. 59 0
      Masuit.Tools.Core/Mapping/Exceptions/ReadOnlyPropertyException.cs
  16. 10 0
      Masuit.Tools.Core/Mapping/ExpressionCpoier.cs
  17. 176 0
      Masuit.Tools.Core/Mapping/ExpressionMapper.cs
  18. 77 0
      Masuit.Tools.Core/Mapping/Extensions/ExpressionExtentions.cs
  19. 124 0
      Masuit.Tools.Core/Mapping/Extensions/QueryableExtentions.cs
  20. 34 0
      Masuit.Tools.Core/Mapping/Helper/MapperHelper.cs
  21. 64 0
      Masuit.Tools.Core/Mapping/Helper/TypeSystem.cs
  22. 26 0
      Masuit.Tools.Core/Mapping/Visitor/ChangParameterExpressionVisitor.cs
  23. 109 0
      Masuit.Tools.Core/Mapping/Visitor/ConverterExpressionVisitor.cs
  24. 203 0
      Masuit.Tools.Core/Mapping/Visitor/MapperExpressionVisitor.cs
  25. 35 0
      Masuit.Tools.Core/Mapping/Visitor/PropertiesVisitor.cs

+ 70 - 0
Masuit.Tools.Core/Mapping/Copier.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping
+{
+    public static class Copier<T>
+    {
+        private static readonly ParameterExpression ParameterExpression = Expression.Parameter(typeof(T), "p");
+        private static Func<T, T> _func;
+        private static readonly Dictionary<string, Expression> DictRule = new Dictionary<string, Expression>();
+
+        /// <summary>
+        /// 深拷贝
+        /// </summary>
+        /// <param name="source"></param>
+        /// <returns></returns>
+        public static T Copy(T source)
+        {
+            if (_func == null)
+            {
+                List<MemberBinding> memberBindings = new List<MemberBinding>();
+                foreach (var item in typeof(T).GetProperties())
+                {
+                    if (DictRule.ContainsKey(item.Name))
+                    {
+                        MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
+                        memberBindings.Add(memberBinding);
+                    }
+                    else
+                    {
+                        var tInProperty = typeof(T).GetProperty(item.Name);
+                        var tInField = typeof(T).GetField(item.Name);
+                        if (tInProperty != null || tInField != null)
+                        {
+                            MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
+                            MemberBinding memberBinding = Expression.Bind(item, property);
+                            memberBindings.Add(memberBinding);
+                        }
+                    }
+                }
+
+                foreach (var item in typeof(T).GetFields())
+                {
+                    if (DictRule.ContainsKey(item.Name))
+                    {
+                        MemberBinding memberBinding = Expression.Bind(item, DictRule[item.Name]);
+                        memberBindings.Add(memberBinding);
+                    }
+                    else
+                    {
+                        var tInProperty = typeof(T).GetProperty(item.Name);
+                        var tInField = typeof(T).GetField(item.Name);
+                        if (tInProperty != null || tInField != null)
+                        {
+                            MemberExpression property = Expression.PropertyOrField(ParameterExpression, item.Name);
+                            MemberBinding memberBinding = Expression.Bind(item, property);
+                            memberBindings.Add(memberBinding);
+                        }
+                    }
+                }
+
+                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindings.ToArray());
+                Expression<Func<T, T>> lambda = Expression.Lambda<Func<T, T>>(memberInitExpression, ParameterExpression);
+                _func = lambda.Compile();
+            }
+            return _func.Invoke(source);
+        }
+    }
+}

+ 12 - 0
Masuit.Tools.Core/Mapping/Core/CreateConfig.cs

@@ -0,0 +1,12 @@
+namespace Masuit.Tools.Mapping.Core
+{
+    /// <summary>
+    /// 映射配置对象
+    /// </summary>
+    internal class CreateConfig
+    {
+        public bool CanCreate { get; set; }
+
+        public string MapperName { get; set; }
+    }
+}

+ 193 - 0
Masuit.Tools.Core/Mapping/Core/MapperConfiguration.cs

@@ -0,0 +1,193 @@
+using Masuit.Tools.Mapping.Exceptions;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Masuit.Tools.Mapping.Core
+{
+    /// <summary>
+    /// 主映射器
+    /// </summary>
+    /// <typeparam name="TSource">源类型</typeparam>
+    /// <typeparam name="TDest">目标类型</typeparam>
+    public class MapperConfiguration<TSource, TDest> : MapperConfigurationBase
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        protected readonly IList<Action<TSource, TDest>> actionsAfterMap;
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public MapperConfiguration(string paramName, string mapperName = null) : base(typeof(TSource), typeof(TDest), paramName, mapperName)
+        {
+            actionsAfterMap = new List<Action<TSource, TDest>>();
+        }
+
+        /// <summary>
+        /// 获取Lambda表达式树
+        /// </summary>
+        /// <returns></returns>
+        public Expression<Func<TSource, TDest>> GetLambdaExpression()
+        {
+            MemberInitExpression exp = GetMemberInitExpression();
+            return Expression.Lambda<Func<TSource, TDest>>(exp, paramClassSource);
+        }
+
+        /// <summary>
+        /// 获取委托
+        /// </summary>
+        /// <returns></returns>
+        public Func<TSource, TDest> GetFuncDelegate()
+        {
+            return (Func<TSource, TDest>)GetDelegate();
+        }
+
+        /// <summary>
+        /// 映射成员
+        /// </summary>
+        /// <param name="getPropertySource">源类型</param>
+        /// <param name="getPropertyDest">目标类型</param>
+        /// <returns></returns>
+        public MapperConfiguration<TSource, TDest> ForMember<TPropertySource, TPropertyDest>(Expression<Func<TSource, TPropertySource>> getPropertySource, Expression<Func<TDest, TPropertyDest>> getPropertyDest)
+        {
+            // 添加到映射列表并且可以继续操作
+            ForMemberBase(getPropertySource.Body, getPropertyDest.Body, false);
+            return this;
+        }
+
+        /// <summary>
+        /// 映射成员
+        /// </summary>
+        /// <typeparam name="TPropertySource">属性源类型</typeparam>
+        /// <typeparam name="TPropertyDest">属性目标类型</typeparam>
+        /// <param name="getPropertySource">源类型</param>
+        /// <param name="getPropertyDest">目标类型</param>
+        /// <param name="checkIfNull">是否检查null值</param>
+        /// <returns></returns>
+        public MapperConfiguration<TSource, TDest> ForMember<TPropertySource, TPropertyDest>(Expression<Func<TSource, TPropertySource>> getPropertySource, Expression<Func<TDest, TPropertyDest>> getPropertyDest, bool checkIfNull)
+        {
+            // 添加到映射列表并且可以继续操作
+            ForMemberBase(getPropertySource.Body, getPropertyDest.Body, checkIfNull);
+            return this;
+        }
+
+        /// <summary>
+        /// 映射成员
+        /// </summary>
+        /// <typeparam name="TPropertySource">属性源类型</typeparam>
+        /// <typeparam name="TPropertyDest">属性目标类型</typeparam>
+        /// <param name="getPropertySource">源类型</param>
+        /// <param name="getPropertyDest">目标类型</param>
+        /// <param name="mapperName">mapper别名</param>
+        /// <returns></returns>
+        public MapperConfiguration<TSource, TDest> ForMember<TPropertySource, TPropertyDest>(Expression<Func<TSource, TPropertySource>> getPropertySource, Expression<Func<TDest, TPropertyDest>> getPropertyDest, string mapperName)
+        {
+            // 添加到映射列表并且可以继续操作
+            ForMemberBase(getPropertySource.Body, getPropertyDest.Body, true, mapperName);
+            return this;
+        }
+
+        /// <summary>
+        /// 忽略一些不需要映射的成员
+        /// </summary>
+        /// <param name="propertyDest">属性名</param>
+        /// <returns></returns>
+        public MapperConfiguration<TSource, TDest> Ignore<TProperty>(Expression<Func<TDest, TProperty>> propertyDest)
+        {
+            return IgnoreBase(propertyDest) as MapperConfiguration<TSource, TDest>;
+        }
+
+        /// <summary>
+        /// 映射后要执行的操作
+        /// </summary>
+        /// <param name="actionAfterMap">映射后要执行的操作</param>
+        /// <returns></returns>
+        public MapperConfiguration<TSource, TDest> AfterMap(Action<TSource, TDest> actionAfterMap)
+        {
+            // 添加到映射列表并且可以继续操作
+            actionsAfterMap.Add(actionAfterMap);
+            return this;
+        }
+
+        /// <summary>
+        /// 执行后续操作。
+        /// </summary>
+        /// <param name="source">源类型</param>
+        /// <param name="dest">目标类型</param>
+        public void ExecuteAfterActions(TSource source, TDest dest)
+        {
+            if (actionsAfterMap.Count > 0)
+            {
+                foreach (var action in actionsAfterMap)
+                {
+                    if (action == null)
+                    {
+                        throw new NoActionAfterMappingException();
+                    }
+                    action(source, dest);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 反向映射
+        /// </summary>
+        /// <param name="name">mapper别名</param>
+        /// <returns>
+        /// 新的mapper对象
+        /// </returns>
+        /// <exception cref="MapperExistException"></exception>
+        public MapperConfiguration<TDest, TSource> ReverseMap(string name = null)
+        {
+            MapperConfigurationBase map = GetMapper(typeof(TDest), typeof(TSource), false, name);
+
+            if (map != null)
+            {
+                throw new MapperExistException(typeof(TDest), typeof(TSource));
+            }
+            string finalName = string.IsNullOrEmpty(name) ? "s" + (MapperConfigurationCollectionContainer.Instance.Count).ToString() : name;
+            map = new MapperConfiguration<TDest, TSource>(finalName);
+            MapperConfigurationCollectionContainer.Instance.Add(map);
+            CreateCommonMember();
+
+            // 现有属性的映射,并且创建反向关系
+            foreach (var item in PropertiesMapping)
+            {
+                PropertyInfo propertyDest = GetPropertyInfo(item.Item1);
+                if (propertyDest.CanWrite)
+                {
+                    if (!string.IsNullOrEmpty(item.Item4))
+                    {
+                        //找到反向关系的mapper
+                        var reverseMapper = GetMapper(item.Item2.Type, item.Item1.Type, false);
+                        if (reverseMapper != null)
+                        {
+                            map.ForMemberBase(item.Item2, item.Item1, item.Item3, reverseMapper.Name);
+                        }
+                    }
+                    else
+                    {
+                        if (item.Item1.NodeType == ExpressionType.MemberAccess)
+                        {
+                            map.ForMemberBase(item.Item2, item.Item1, item.Item3, item.Item4);
+                        }
+                    }
+                }
+            }
+
+            return (MapperConfiguration<TDest, TSource>)map;
+        }
+
+        /// <summary>
+        /// 是否使用服务注入
+        /// </summary>
+        public MapperConfiguration<TSource, TDest> ConstructUsingServiceLocator()
+        {
+            UseServiceLocator = true;
+            return this;
+        }
+    }
+}

+ 667 - 0
Masuit.Tools.Core/Mapping/Core/MapperConfigurationBase.cs

@@ -0,0 +1,667 @@
+using Masuit.Tools.Mapping.Exceptions;
+using Masuit.Tools.Mapping.Helper;
+using Masuit.Tools.Mapping.Visitor;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Masuit.Tools.Mapping.Core
+{
+    /// <summary>
+    /// mapper配置基类
+    /// </summary>
+    public abstract class MapperConfigurationBase
+    {
+        private Delegate _delegateCallForNew;
+
+        private Delegate _delegateCallForExisting;
+
+        private Func<Type, object> _constructorFunc;
+
+        private bool _isInitialized;
+        private readonly MethodInfo _selectMethod;
+
+        private readonly MethodInfo _toListMethod;
+
+        private readonly List<PropertyInfo> _propertiesToIgnore;
+
+        internal ParameterExpression paramClassSource;
+        internal MapperExpressionVisitor visitorMapper;
+        internal List<MemberAssignment> memberForNew;
+        internal LambdaExpression expressionForExisting;
+
+        /// <summary>
+        /// 属性映射对应关系<br/>
+        /// Item1 : 源表达式<br/>
+        /// Item2 : 目标表达式<br/>
+        /// Item3 : 检查null值<br/>
+        /// Item4 : mapper别名<br/>
+        /// </summary>
+        protected List<Tuple<Expression, Expression, bool, string>> PropertiesMapping { get; private set; }
+
+
+        /// <summary>
+        /// 需要被忽略映射的属性
+        /// </summary>
+        protected ReadOnlyCollection<PropertyInfo> PropertiesToIgnore => _propertiesToIgnore.AsReadOnly();
+
+        /// <summary>
+        /// 是否使用服务依赖注入
+        /// </summary>
+        public bool UseServiceLocator { get; protected set; }
+
+        /// <summary>
+        /// 对象源类型
+        /// </summary>
+        public Type SourceType { get; private set; }
+
+        /// <summary>
+        /// 对象目标类型
+        /// </summary>
+        public Type TargetType { get; private set; }
+
+        /// <summary>
+        /// 获取mapper映射成员
+        /// </summary>
+        public ReadOnlyCollection<MemberAssignment> MemberToMapForNew => new ReadOnlyCollection<MemberAssignment>(memberForNew);
+
+
+        /// <summary>
+        /// mapper别名
+        /// </summary>
+        public string Name { get; protected set; }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="source">源类型</param>
+        /// <param name="destination">目标类型</param>
+        /// <param name="paramName">属性名</param>
+        /// <param name="name">别名</param>
+        protected MapperConfigurationBase(Type source, Type destination, string paramName, string name = null)
+        {
+            TargetType = destination;
+            SourceType = source;
+            paramClassSource = Expression.Parameter(source, paramName);
+            Name = string.IsNullOrEmpty(name) ? paramName : name;
+            _propertiesToIgnore = new List<PropertyInfo>();
+            PropertiesMapping = new List<Tuple<Expression, Expression, bool, string>>();
+            visitorMapper = new MapperExpressionVisitor(paramClassSource);
+            memberForNew = new List<MemberAssignment>();
+            _selectMethod = typeof(Enumerable).GetMethods().Where(m => m.Name == "Select").Select(x => x.GetParameters().First(p => p.Name.Equals("selector") && p.ParameterType.GetGenericArguments().Length == 2)).First().Member as MethodInfo;
+            _toListMethod = typeof(Enumerable).GetMethod("ToList");
+        }
+
+        /// <summary>
+        /// 获取mapper委托
+        /// </summary>
+        /// <returns></returns>
+        public Delegate GetDelegate()
+        {
+            if (!_isInitialized)
+            {
+                throw new MapperNotInitializedException(SourceType, TargetType);
+            }
+
+            // 因为在这里有映射器的性能问题,而缓存委托会显着缩短处理时间,如果没有表达式编译每次编译会很慢
+            if (_delegateCallForNew == null)
+            {
+                MemberInitExpression exp = GetMemberInitExpression();
+
+                _delegateCallForNew = Expression.Lambda(exp, paramClassSource).Compile();
+            }
+
+            return _delegateCallForNew;
+        }
+
+        /// <summary>
+        /// 获取现有目标类型的委托。
+        /// </summary>
+        /// <exception cref="MapperNotInitializedException"></exception>
+        public Delegate GetDelegateForExistingTarget()
+        {
+            if (!_isInitialized)
+            {
+                throw new MapperNotInitializedException(SourceType, TargetType);
+            }
+
+            // 因为在这里有映射器的性能问题,而缓存委托会显着缩短处理时间,如果没有表达式编译每次编译会很慢
+            if (_delegateCallForExisting == null)
+            {
+                CreateMemberAssignementForExistingTarget();
+            }
+
+            return _delegateCallForExisting;
+        }
+
+        /// <summary>
+        /// 获取泛型的Lambda表达式
+        /// </summary>
+        public LambdaExpression GetGenericLambdaExpression()
+        {
+            MemberInitExpression exp = GetMemberInitExpression();
+            return Expression.Lambda(exp, paramClassSource);
+        }
+
+        /// <summary>
+        /// 获取目标类型的实际类型
+        /// </summary>
+        public Type GetDestinationType()
+        {
+            return GetRealType(TargetType);
+        }
+
+        /// <summary>
+        /// 忽略目标类型的属性
+        /// </summary>
+        /// <typeparam name="TDest">对象源类型</typeparam>
+        /// <typeparam name="TProperty">对象目标类型</typeparam>
+        /// <param name="propertyDest">目标对象的属性</param>
+        /// <returns></returns>
+        protected MapperConfigurationBase IgnoreBase<TDest, TProperty>(Expression<Func<TDest, TProperty>> propertyDest)
+        {
+            // 添加到映射列表并且可以继续操作
+            _propertiesToIgnore.Add(GetPropertyInfo(propertyDest));
+            return this;
+        }
+
+        /// <summary>
+        /// 获取映射器实例
+        /// </summary>
+        /// <param name="typeOfSource">源类型</param>
+        /// <param name="typeOfTarget">目标类型</param>
+        /// <param name="throwExceptionOnNoFound">如果没找到是否需要抛出异常</param>
+        /// <param name="name">mapper别名</param>
+        /// <returns></returns>
+        /// <exception cref="NoFoundMapperException"></exception>
+        protected static MapperConfigurationBase GetMapper(Type typeOfSource, Type typeOfTarget, bool throwExceptionOnNoFound, string name = null)
+        {
+            var mapperExterne = MapperConfigurationCollectionContainer.Instance.Find(typeOfSource, typeOfTarget, name);
+            // 如果没有任何配置,手动抛出异常
+            if (mapperExterne == null && throwExceptionOnNoFound)
+            {
+                throw new NoFoundMapperException(typeOfSource, typeOfTarget);
+            }
+
+            return mapperExterne;
+        }
+
+        /// <summary>
+        /// 创建公共成员
+        /// </summary>
+        protected void CreateCommonMember()
+        {
+            PropertyInfo[] propertiesSource = SourceType.GetProperties();
+            foreach (PropertyInfo propSource in propertiesSource)
+            {
+                PropertyInfo propDest = TargetType.GetProperty(propSource.Name);
+                if (propDest != null)
+                {
+                    // 检查是否已存在或被忽略。
+                    bool ignorePropDest = _propertiesToIgnore.Exists(x => x.Name == propDest.Name) || PropertiesMapping.Exists(x => GetPropertyInfo(x.Item2).Name == propDest.Name);
+
+                    if (propDest.CanWrite && !ignorePropDest)
+                    {
+                        Type sourceType = propSource.PropertyType;
+                        Type destType = propDest.PropertyType;
+                        bool isList = IsListOf(destType);
+                        if (isList)
+                        {
+                            sourceType = TypeSystem.GetElementType(propSource.PropertyType);
+                            destType = TypeSystem.GetElementType(propDest.PropertyType);
+                        }
+
+                        var canCreateConfig = CanCreateConfig(sourceType, destType);
+                        if (canCreateConfig.CanCreate)
+                        {
+                            // 只创造现有的关系
+                            Expression expSource = Expression.MakeMemberAccess(paramClassSource, propSource);
+                            ParameterExpression paramDest = Expression.Parameter(TargetType, "t");
+                            Expression expDest = Expression.MakeMemberAccess(paramDest, propDest);
+                            PropertiesMapping.Add(Tuple.Create(expSource, expDest, false, canCreateConfig.MapperName));
+                        }
+                    }
+                }
+            }
+        }
+
+        private static CreateConfig CanCreateConfig(Type typeSource, Type typeTarget)
+        {
+            CreateConfig result = new CreateConfig
+            {
+                CanCreate = typeSource == typeTarget
+            };
+            //不是同一类型
+            if (!result.CanCreate)
+            {
+                //查找是否存在映射器
+                var mapper = MapperConfigurationCollectionContainer.Instance.Find(typeSource, typeTarget);
+                if (mapper != null)
+                {
+                    result.MapperName = mapper.Name;
+                    result.CanCreate = true;
+                }
+            }
+
+            return result;
+        }
+
+        /// <summary>
+        /// 检查并配置mapper
+        /// </summary>
+        /// <param name="configExpression">配置表达式树</param>
+        /// <exception cref="NotSameTypePropertyException">
+        /// </exception>
+        /// <exception cref="ReadOnlyPropertyException"></exception>
+        protected void CheckAndConfigureMapping(ref Tuple<Expression, Expression, bool, string> configExpression)
+        {
+            Type typeSource = configExpression.Item1.Type;
+            Type typeTarget = configExpression.Item2.Type;
+
+            // 正常情况下,目标表达式是一个成员表达式树
+            PropertyInfo propTarget = GetPropertyInfo(configExpression.Item2);
+
+            if (propTarget.CanWrite)
+            {
+                CheckAndRemoveMemberDest(propTarget.Name);
+                if (!IsListOf(typeTarget))
+                {
+                    CreatBindingFromSimple(ref configExpression, typeSource, typeTarget, propTarget);
+                }
+                else
+                {
+                    CreateBindingFromList(ref configExpression, typeSource, typeTarget, propTarget);
+                }
+            }
+            else
+            {
+                throw new ReadOnlyPropertyException(propTarget);
+            }
+        }
+
+        /// <summary>
+        /// 检查并移除目标成员
+        /// </summary>
+        /// <param name="properyName">属性名</param>
+        protected void CheckAndRemoveMemberDest(string properyName)
+        {
+            Predicate<MemberAssignment> exp = m => m.Member.Name == properyName;
+            if (memberForNew.Exists(exp))
+            {
+                memberForNew.RemoveAll(exp);
+            }
+        }
+
+        /// <summary>
+        /// 获取成员初始化表达式。
+        /// </summary>
+        /// <returns></returns>
+        protected MemberInitExpression GetMemberInitExpression()
+        {
+            Type typeDest = GetDestinationType();
+            NewExpression newClassDest = Expression.New(typeDest);
+            MemberInitExpression exp = Expression.MemberInit(newClassDest, MemberToMapForNew);
+            return exp;
+        }
+
+        /// <summary>
+        /// 创建成员绑定。
+        /// </summary>
+        /// <param name="propertyExpression">属性表达式</param>
+        /// <param name="propertyTarget">目标属性</param>
+        /// <param name="checkIfNull">是否检查null值</param>
+        protected void CreateMemberBinding(Expression propertyExpression, MemberInfo propertyTarget, bool checkIfNull)
+        {
+            // 访问表达式进行转换
+            Expression result = visitorMapper.Visit(propertyExpression, checkIfNull);
+            MemberAssignment bind = Expression.Bind(propertyTarget, result);
+            memberForNew.Add(bind);
+        }
+
+        /// <summary>
+        /// 将表达式源的映射分配给属性目标。
+        /// </summary>
+        /// <param name="getPropertySource">属性源类型</param>
+        /// <param name="getPropertyDest">属性目标类型</param>
+        /// <param name="checkIfNull">是否检查null值</param>
+        /// <param name="name">要使用的映射器的别名</param>
+        internal MapperConfigurationBase ForMemberBase(Expression getPropertySource, Expression getPropertyDest, bool checkIfNull, string name = null)
+        {
+            // 添加到映射列表并且可以继续操作
+            PropertiesMapping.Add(Tuple.Create(getPropertySource, getPropertyDest, checkIfNull, name));
+            return this;
+        }
+
+        /// <summary>
+        /// 获取属性信息。
+        /// </summary>
+        /// <param name="propertyExpression">属性表达式树</param>
+        /// <returns></returns>
+        /// <exception cref="System.NotImplementedException">
+        /// 这种表达方式不承担职责,或者这种类型的表达式是无效的
+        /// </exception>
+        protected static PropertyInfo GetPropertyInfo(Expression propertyExpression)
+        {
+            var expressionToAnalyse = propertyExpression.NodeType == ExpressionType.Lambda ? (propertyExpression as LambdaExpression).Body : propertyExpression;
+            switch (expressionToAnalyse.NodeType)
+            {
+                case ExpressionType.Convert:
+                    Expression operand = (expressionToAnalyse as UnaryExpression).Operand;
+                    switch (operand.NodeType)
+                    {
+                        case ExpressionType.MemberAccess:
+                            return (operand as MemberExpression).Member as PropertyInfo;
+                        default:
+                            throw new NotImplementedException("这种表达方式目前尚未支持");
+                    }
+                case ExpressionType.MemberAccess:
+                    return (expressionToAnalyse as MemberExpression).Member as PropertyInfo;
+                default:
+                    throw new NotImplementedException("这种表达方式目前尚未支持");
+            }
+        }
+
+        internal void Initialize(Func<Type, object> constructor)
+        {
+            CreateMappingExpression(constructor);
+            CreateMemberAssignementForExistingTarget();
+        }
+
+        public virtual void CreateMemberAssignementForExistingTarget()
+        {
+            if (PropertiesMapping.Count > 0)
+            {
+                // 用于更改原始表达式的参数。
+                var paramTarget = Expression.Parameter(TargetType, paramClassSource.Name.Replace("s", "t"));
+                ChangParameterExpressionVisitor visitSource = new ChangParameterExpressionVisitor(paramClassSource);
+                ChangParameterExpressionVisitor visitTarget = new ChangParameterExpressionVisitor(paramTarget);
+
+                List<Expression> finalAssign = new List<Expression>();
+
+                foreach (var item in PropertiesMapping)
+                {
+                    var propToAssign = visitTarget.Visit(item.Item2);
+                    var assignExpression = visitSource.Visit(item.Item1);
+                    Type sourceType = TypeSystem.GetElementType(item.Item2.Type);
+                    Type targetType = TypeSystem.GetElementType(item.Item1.Type);
+                    if (string.IsNullOrEmpty(item.Item4))
+                    {
+                        object defaultValue = MapperHelper.GetDefaultValue(item.Item2.Type);
+                        Expression defaultExpression = Expression.Constant(defaultValue, item.Item2.Type);
+                        Expression checkIfNull = Expression.NotEqual(assignExpression, defaultExpression);
+                        if (item.Item3)
+                        {
+                            Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
+                            finalAssign.Add(setIf);
+                        }
+                        else
+                        {
+                            if (!IsListOf(propToAssign.Type))
+                            {
+                                finalAssign.Add(Expression.Assign(propToAssign, assignExpression));
+                            }
+                            else
+                            {
+                                if (sourceType == targetType)
+                                {
+                                    Expression toListExp = Expression.Call(_toListMethod.MakeGenericMethod(sourceType), assignExpression);
+                                    Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
+                                    finalAssign.Add(setIf);
+                                }
+                            }
+                        }
+                    }
+                    else // 来自其他映射器。
+                    {
+                        var mapper = GetMapper(sourceType, targetType, false, item.Item4);
+                        if (mapper != null)
+                        {
+                            mapper.Initialize(_constructorFunc);
+
+                            Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(item.Item2.Type), item.Item2.Type);
+                            if (!IsListOf(propToAssign.Type))
+                            {
+                                ChangParameterExpressionVisitor changeVisitor = new ChangParameterExpressionVisitor(propToAssign, assignExpression);
+
+                                Expression modifiedExpression = changeVisitor.Visit(mapper.expressionForExisting.Body);
+                                Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
+                                Expression setIf = Expression.IfThen(checkIfNull, modifiedExpression);
+                                assignExpression = setIf;
+                            }
+                            else
+                            {
+                                Expression selectExp = Expression.Call(_selectMethod.MakeGenericMethod(sourceType), Expression.Constant(mapper.GetDelegate()));
+                                Expression checkIfNull = Expression.NotEqual(propToAssign, defaultExpression);
+                                Expression setIf = Expression.IfThen(checkIfNull, Expression.Assign(propToAssign, assignExpression));
+                                assignExpression = setIf;
+                            }
+
+                            finalAssign.Add(assignExpression);
+                        }
+                    }
+                }
+
+                if (finalAssign.Count > 0 && _delegateCallForExisting == null)
+                {
+                    expressionForExisting = Expression.Lambda(Expression.Block(typeof(void), finalAssign), paramClassSource, paramTarget);
+                    // 编译
+                    _delegateCallForExisting = expressionForExisting.Compile();
+                }
+            }
+        }
+
+        internal Expression GetLambdaDest(string propertyName)
+        {
+            var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item1).Name == propertyName);
+            if (exp != null)
+            {
+                var final = exp.Item2;
+                if (final.NodeType == ExpressionType.Convert)
+                {
+                    final = (final as UnaryExpression).Operand;
+                }
+
+                return final;
+            }
+
+            return null;
+        }
+
+        public virtual void CreateMappingExpression(Func<Type, object> constructor)
+        {
+            if (!_isInitialized)
+            {
+                // 它是在处理前放置以避免递归循环。
+                _isInitialized = true;
+                _constructorFunc = constructor;
+                CreateCommonMember();
+                var propsToAnalyse = PropertiesMapping.ToList(); // 克隆列表以便于更改。
+                for (int i = 0; i < propsToAnalyse.Count; i++)
+                {
+                    var propToAnalyse = propsToAnalyse[i];
+                    CheckAndConfigureMapping(ref propToAnalyse);
+                    propsToAnalyse[i] = propToAnalyse;
+                }
+
+                PropertiesMapping = propsToAnalyse;
+                // 编译
+                GetDelegate();
+            }
+        }
+
+        internal Type GetRealType(Type typeToFind)
+        {
+            if (UseServiceLocator)
+                return _constructorFunc(typeToFind).GetType();
+            return typeToFind;
+        }
+
+        internal PropertiesNotMapped GetPropertiesNotMapped()
+        {
+            PropertiesNotMapped result = new PropertiesNotMapped();
+            // 克隆属性信息
+            List<PropertyInfo> sourceProperties = SourceType.GetProperties().ToList();
+            List<PropertyInfo> targetProperties = TargetType.GetProperties().ToList();
+
+            PropertiesVisitor visitor = new PropertiesVisitor(TargetType);
+            foreach (var members in memberForNew)
+            {
+                var members1 = members;
+                sourceProperties.RemoveAll((p) => members1.Member.Name == p.Name);
+                targetProperties.RemoveAll((p) => visitor.GetProperties(members.Expression).Contains(p));
+            }
+
+            // 检查被忽略映射的成员
+            sourceProperties.RemoveAll((p) => _propertiesToIgnore.Contains(p));
+            result.sourceProperties = sourceProperties;
+            result.targetProperties = targetProperties;
+
+            return result;
+        }
+
+        public LambdaExpression GetSortedExpression(string propertySource)
+        {
+            Expression result = null;
+            var exp = PropertiesMapping.Find(x => GetPropertyInfo(x.Item2).Name == propertySource);
+            if (exp == null)
+            {
+                throw new PropertyNoExistException(propertySource, TargetType);
+            }
+
+            // 更改参数
+            var visitor = new MapperExpressionVisitor(paramClassSource);
+            result = visitor.Visit(exp.Item1);
+            return Expression.Lambda(result, paramClassSource);
+        }
+
+        private static bool IsListOf(Type typeTarget)
+        {
+            // 特殊情况字符串是char数组。
+            if (typeTarget == typeof(string))
+            {
+                return false;
+            }
+
+            Func<Type, bool> test = t => t.IsAssignableFrom(typeof(IEnumerable));
+            return test(typeTarget) || typeTarget.GetInterfaces().Any(test);
+        }
+
+        private MapperConfigurationBase GetAndCheckMapper(Type typeOfSource, Type typeOfTarget, string name)
+        {
+            var externalMapper = GetMapper(typeOfSource, typeOfTarget, false, name);
+            if (externalMapper != null)
+            {
+                return externalMapper;
+            }
+
+            //如果找不到具有别名的映射器
+            if (!string.IsNullOrEmpty(name))
+            {
+                throw new NoFoundMapperException(name);
+            }
+
+            throw new NotSameTypePropertyException(typeOfSource, typeOfTarget);
+        }
+
+        private void CreatBindingFromSimple(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
+        {
+            // 没有特殊的操作
+            if (typeSource == typeTarget)
+            {
+                // 创建成员绑定
+                CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
+            }
+            else
+            {
+                // 尝试查找mapper
+                MapperConfigurationBase externalMapper = GetAndCheckMapper(typeSource, typeTarget, configExpression.Item4);
+                // 如果此时未初始化映射器
+                externalMapper.CreateMappingExpression(_constructorFunc);
+                // 默认情况下,检查对象的null
+                Expression mapExpression = externalMapper.GetMemberInitExpression();
+                Expression defaultExpression = Expression.Constant(MapperHelper.GetDefaultValue(configExpression.Item1.Type), configExpression.Item1.Type);
+                // 修改成员
+                Expression expSource = visitorMapper.Visit(configExpression.Item1, false);
+                ChangParameterExpressionVisitor changeParamaterVisitor = new ChangParameterExpressionVisitor(expSource);
+                mapExpression = changeParamaterVisitor.Visit(mapExpression);
+                // 现在可以创建正确的参数。
+                Expression checkIfNull = Expression.NotEqual(expSource, defaultExpression);
+                // 创建条件
+                var checkExpression = Expression.Condition(checkIfNull, mapExpression, Expression.Constant(MapperHelper.GetDefaultValue(mapExpression.Type), mapExpression.Type), mapExpression.Type);
+                MemberAssignment bindExpression = Expression.Bind(propTarget, checkExpression);
+                // 找到了映射器但没有配置
+                if (string.IsNullOrEmpty(configExpression.Item4))
+                {
+                    configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
+                }
+
+                memberForNew.Add(bindExpression);
+            }
+        }
+
+        private void CreateBindingFromList(ref Tuple<Expression, Expression, bool, string> configExpression, Type typeSource, Type typeTarget, PropertyInfo propTarget)
+        {
+            Type sourceTypeList = TypeSystem.GetElementType(typeSource);
+            Type destTypeList = TypeSystem.GetElementType(typeTarget);
+            if (sourceTypeList == destTypeList)
+            {
+                if (configExpression.Item2.NodeType == ExpressionType.MemberAccess)
+                {
+                    CreateMemberBinding(configExpression.Item1, propTarget, configExpression.Item3);
+                }
+            }
+            // 使用Enumerable类的select方法来更改类型
+            else
+            {
+                var externalMapper = GetAndCheckMapper(sourceTypeList, destTypeList, configExpression.Item4);
+                externalMapper.CreateMappingExpression(_constructorFunc);
+                MemberAssignment expBind;
+                Expression expSource = configExpression.Item1;
+
+                ChangParameterExpressionVisitor visitor = new ChangParameterExpressionVisitor(paramClassSource);
+                expSource = visitor.Visit(expSource);
+
+                // 为了与EF / LINQ2SQL兼容。
+                LambdaExpression expMappeur = externalMapper.GetGenericLambdaExpression();
+                // 创建对Select方法的调用,在Enumerable的Select中插入一个lambda表达式(参数是一个委托),通常情况下,这是不可能的,但(个人认为)编译器就像这样创建并且LINQ2SQL / EF是可以进行sql查询的
+                Expression select = Expression.Call(_selectMethod.MakeGenericMethod(sourceTypeList, destTypeList), new Expression[]
+                {
+                    expSource,
+                    expMappeur
+                });
+                // 创建对ToList方法的调用
+                Expression toList = Expression.Call(_toListMethod.MakeGenericMethod(destTypeList), select);
+
+                if (configExpression.Item3) // 如果要检查无效(使用EF / LinqTosql,则不需要)。
+                {
+                    // 测试source的属性是否为null。
+                    Expression checkIfNull = Expression.NotEqual(expSource, Expression.Constant(MapperHelper.GetDefaultValue(expSource.Type), expSource.Type));
+                    // 有时候ToList方法不起作用,则使用实现ToList不起作用的类
+                    Expression asExp = Expression.TypeAs(toList, propTarget.PropertyType);
+                    // 创建条件表达式
+                    Expression expCondition = Expression.Condition(checkIfNull, asExp, Expression.Constant(MapperHelper.GetDefaultValue(typeTarget), typeTarget));
+
+                    // 分配给目标属性。
+                    expBind = Expression.Bind(propTarget, expCondition);
+                }
+                else
+                {
+                    // 分配给目标属性。
+                    expBind = Expression.Bind(propTarget, toList);
+                }
+
+                // 查找mapper
+                if (string.IsNullOrEmpty(configExpression.Item4))
+                {
+                    configExpression = Tuple.Create(configExpression.Item1, configExpression.Item2, configExpression.Item3, externalMapper.Name);
+                }
+
+                memberForNew.Add(expBind);
+            }
+        }
+    }
+}

+ 108 - 0
Masuit.Tools.Core/Mapping/Core/MapperConfigurationCollectionContainer.cs

@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Masuit.Tools.Mapping.Core
+{
+    /// <summary>
+    /// 单例存储映射器。
+    /// </summary>
+    /// <remarks>不需要单例,因为适用于所有线程。</remarks>
+    public class MapperConfigurationCollectionContainer : IEnumerable<MapperConfigurationBase>
+    {
+        private readonly HashSet<MapperConfigurationBase> _items;
+        private static MapperConfigurationCollectionContainer currentInstance;
+
+        private MapperConfigurationCollectionContainer()
+        {
+            _items = new HashSet<MapperConfigurationBase>();
+        }
+
+
+        public static MapperConfigurationCollectionContainer Instance => currentInstance ?? (currentInstance = new MapperConfigurationCollectionContainer());
+
+        public int Count => _items.Count;
+
+        internal MapperConfigurationBase this[int index]
+        {
+            get
+            {
+                if (index > _items.Count)
+                    throw new IndexOutOfRangeException();
+                var enumerator = GetEnumerator();
+                int i = 0;
+                while (enumerator.MoveNext())
+                {
+                    if (i == index)
+                    {
+                        return enumerator.Current;
+                    }
+                    i++;
+                }
+
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// 查找指定的源。
+        /// </summary>
+        /// <param name="source">源类型</param>
+        /// <param name="target">目标对象</param>
+        /// <param name="name">别名</param>
+        internal MapperConfigurationBase Find(Type source, Type target, string name = null)
+        {
+            foreach (var current in this)
+            {
+                string nameMapper = string.IsNullOrEmpty(name) ? current.paramClassSource.Name : name;
+                if (current.SourceType == source && current.TargetType == target && current.Name == nameMapper)
+                {
+                    return current;
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// 是否存在谓词的映射。
+        /// </summary>
+        /// <param name="match">条件表达式</param>
+        public bool Exists(Func<MapperConfigurationBase, bool> match)
+        {
+            return this.Any(match);
+        }
+
+        public void RemoveAt(int index)
+        {
+            MapperConfigurationBase itemToDelete = this[index];
+            if (itemToDelete != null)
+            {
+                _items.Remove(itemToDelete);
+            }
+        }
+
+        /// <summary>
+        /// 清除
+        /// </summary>
+        public void Clear()
+        {
+            _items.Clear();
+        }
+
+        public void Add(MapperConfigurationBase value)
+        {
+            _items.Add(value);
+        }
+
+        public IEnumerator<MapperConfigurationBase> GetEnumerator()
+        {
+            return _items.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+}

+ 35 - 0
Masuit.Tools.Core/Mapping/Core/PropertiesNotMapped.cs

@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Reflection;
+
+namespace Masuit.Tools.Mapping.Core
+{
+    /// <summary>
+    /// 未映射的属性的处理结果。
+    /// </summary>
+    public class PropertiesNotMapped
+    {
+
+        internal List<PropertyInfo> sourceProperties;
+        internal List<PropertyInfo> targetProperties;
+
+        /// <summary>
+        /// 获取未映射的源属性。
+        /// </summary>
+        public ReadOnlyCollection<PropertyInfo> SourceProperties => new ReadOnlyCollection<PropertyInfo>(sourceProperties);
+
+        /// <summary>
+        /// 获取未映射的目标属性。
+        /// </summary>
+        public ReadOnlyCollection<PropertyInfo> TargetProperties => new ReadOnlyCollection<PropertyInfo>(targetProperties);
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public PropertiesNotMapped()
+        {
+            sourceProperties = new List<PropertyInfo>();
+            targetProperties = new List<PropertyInfo>();
+        }
+    }
+}

+ 59 - 0
Masuit.Tools.Core/Mapping/Core/TypePairMapper.cs

@@ -0,0 +1,59 @@
+using System;
+
+namespace Masuit.Tools.Mapping.Core
+{
+    internal struct TypePairMapper : IEquatable<TypePairMapper>
+    {
+        public TypePairMapper(Type source, Type target, string name = null) : this()
+        {
+            Target = target;
+            Source = source;
+            Name = name;
+        }
+
+        public Type Source { get; private set; }
+        public Type Target { get; private set; }
+
+        public string Name { get; private set; }
+
+        public static TypePairMapper Create(Type source, Type target, string name = null)
+        {
+            return new TypePairMapper(source, target, name);
+        }
+
+        public static TypePairMapper Create<TSource, TTarget>(string name = null)
+        {
+            return new TypePairMapper(typeof(TSource), typeof(TTarget), name);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj))
+            {
+                return false;
+            }
+            return obj is TypePairMapper && Equals((TypePairMapper)obj);
+        }
+
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                return ((Source != null ? Source.GetHashCode() : 0) * 397) ^ (Target != null ? Target.GetHashCode() : 0);
+            }
+        }
+        public bool Equals(TypePairMapper other)
+        {
+            bool result;
+            if (!string.IsNullOrEmpty(other.Name))
+            {
+                result = Source == other.Source && Target == other.Target && Name == other.Name;
+            }
+            else
+            {
+                result = Source == other.Source && Target == other.Target;
+            }
+            return result;
+        }
+    }
+}

+ 56 - 0
Masuit.Tools.Core/Mapping/Exceptions/MapperExceptionBase.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// mapper异常基类
+    /// </summary>
+    [Serializable]
+    public class MapperExceptionBase : Exception
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public MapperExceptionBase(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        /// <summary>
+        /// 无参构造函数
+        /// </summary>
+        public MapperExceptionBase()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected MapperExceptionBase(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public MapperExceptionBase(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+
+        /// <summary>
+        /// 验证参数
+        /// </summary>
+        /// <param name="message">消息</param>
+        /// <param name="conditions">条件</param>
+        /// <returns>异常信息</returns>
+        protected static string ValideParameter(string message, params bool[] conditions)
+        {
+            return message;
+        }
+    }
+}

+ 55 - 0
Masuit.Tools.Core/Mapping/Exceptions/MapperExistException.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 映射已存在时的异常
+    /// </summary>
+    [Serializable]
+    public class MapperExistException : MapperExceptionBase
+
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="source">源类型</param>
+        /// <param name="dest">目标类型</param>
+        public MapperExistException(Type source, Type dest) : base(ValideParameter($"对于源“{source.FullName}”的类型和目标类型“{dest.FullName}”的映射关系已经存在", source != null, dest != null))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public MapperExistException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public MapperExistException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected MapperExistException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public MapperExistException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+    }
+}

+ 54 - 0
Masuit.Tools.Core/Mapping/Exceptions/MapperNotInitializedException.cs

@@ -0,0 +1,54 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 映射未初始化时的异常
+    /// </summary>
+    [Serializable]
+    public class MapperNotInitializedException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="typeSource">源类型</param>
+        /// <param name="typeDest">目标类型</param>
+        public MapperNotInitializedException(Type typeSource, Type typeDest) : base(ValideParameter($"源类型“{typeSource.FullName}”和目标类型“{typeDest.FullName}”的映射关系未被初始化,需要在此之前调用ExpressionMapper.Initialize()", typeSource != null, typeDest != null))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public MapperNotInitializedException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public MapperNotInitializedException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected MapperNotInitializedException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public MapperNotInitializedException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+    }
+}

+ 46 - 0
Masuit.Tools.Core/Mapping/Exceptions/NoActionAfterMappingException.cs

@@ -0,0 +1,46 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 无法执行任何操作时的异常
+    /// </summary>
+    /// <seealso cref="MapperExceptionBase" />
+    [Serializable]
+    public class NoActionAfterMappingException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public NoActionAfterMappingException() : base("无法执行操作,因为操作未定义")
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected NoActionAfterMappingException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public NoActionAfterMappingException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public NoActionAfterMappingException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+    }
+}

+ 54 - 0
Masuit.Tools.Core/Mapping/Exceptions/NoFoundMapperException.cs

@@ -0,0 +1,54 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 未找到映射关系时出现异常
+    /// </summary>
+    [Serializable]
+    public class NoFoundMapperException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="source">源类型</param>
+        /// <param name="dest">目标类型</param>
+        public NoFoundMapperException(Type source, Type dest) : base(ValideParameter($"未配置类型“{source.Name}”和“{dest.Name}”的映射", source != null, dest != null))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="name">别名</param>
+        public NoFoundMapperException(string name) : base(ValideParameter($"找不到名称为{name}的映射", !string.IsNullOrEmpty(name)))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public NoFoundMapperException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected NoFoundMapperException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public NoFoundMapperException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+    }
+}

+ 53 - 0
Masuit.Tools.Core/Mapping/Exceptions/NotSameTypePropertyException.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 当属性不是同一类型或找不到映射器时出现异常
+    /// </summary>
+    [Serializable]
+    public class NotSameTypePropertyException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="typeSource">源类型</param>
+        /// <param name="typeDest">目标类型</param>
+        public NotSameTypePropertyException(Type typeSource, Type typeDest) : base(ValideParameter($"源类型{typeSource.Name}目标和类型{typeDest.Name}的属性不是同一类型或找不到映射关系", typeSource != null, typeDest != null))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public NotSameTypePropertyException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected NotSameTypePropertyException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public NotSameTypePropertyException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public NotSameTypePropertyException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+    }
+}

+ 54 - 0
Masuit.Tools.Core/Mapping/Exceptions/PropertyNoExistException.cs

@@ -0,0 +1,54 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 找不到属性时出现异常
+    /// </summary>
+    [Serializable]
+    public class PropertyNoExistException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="propertyName">属性名</param>
+        /// <param name="typeObject">对象类型</param>
+        public PropertyNoExistException(string propertyName, Type typeObject) : base(ValideParameter($"类型“{typeObject}”不存在属性“{propertyName}”", !String.IsNullOrEmpty(propertyName), typeObject != null))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public PropertyNoExistException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public PropertyNoExistException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected PropertyNoExistException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public PropertyNoExistException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+    }
+}

+ 59 - 0
Masuit.Tools.Core/Mapping/Exceptions/ReadOnlyPropertyException.cs

@@ -0,0 +1,59 @@
+using System;
+using System.Reflection;
+using System.Runtime.Serialization;
+
+namespace Masuit.Tools.Mapping.Exceptions
+{
+    /// <summary>
+    /// 只读属性的异常
+    /// </summary>
+    [Serializable]
+    public class ReadOnlyPropertyException : MapperExceptionBase
+    {
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="property">属性</param>
+        public ReadOnlyPropertyException(PropertyInfo property) : base(ValidateParameter(property))
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        public ReadOnlyPropertyException()
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="serializer">序列化信息</param>
+        /// <param name="context">上下文</param>
+        protected ReadOnlyPropertyException(SerializationInfo serializer, StreamingContext context) : base(serializer, context)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        /// <param name="innerException">内部异常</param>
+        public ReadOnlyPropertyException(string exceptionMessage, Exception innerException) : base(exceptionMessage, innerException)
+        {
+        }
+
+        /// <summary>
+        /// 构造函数
+        /// </summary>
+        /// <param name="exceptionMessage">异常信息</param>
+        public ReadOnlyPropertyException(string exceptionMessage) : base(exceptionMessage)
+        {
+        }
+
+        private static string ValidateParameter(PropertyInfo property)
+        {
+            return $"目标对象的属性 '{property.Name}' 是只读的";
+        }
+    }
+}

+ 10 - 0
Masuit.Tools.Core/Mapping/ExpressionCpoier.cs

@@ -0,0 +1,10 @@
+namespace Masuit.Tools.Mapping
+{
+    public static class ExpressionCpoier
+    {
+        public static T Copy<T>(this T source)
+        {
+            return Copier<T>.Copy(source);
+        }
+    }
+}

+ 176 - 0
Masuit.Tools.Core/Mapping/ExpressionMapper.cs

@@ -0,0 +1,176 @@
+using Masuit.Tools.Mapping.Core;
+using Masuit.Tools.Mapping.Exceptions;
+using System;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping
+{
+    /// <summary>
+    /// mapper的基类
+    /// </summary>
+    public static class ExpressionMapper
+    {
+        private static Func<Type, object> _constructorFunc;
+        private static bool _initialized;
+
+        /// <summary>
+        /// 映射指定的源。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="source">源对象</param>
+        /// <param name="name">别名</param>
+        /// <returns>
+        /// 目标对象的新实例
+        /// </returns>
+        public static TTarget Map<TSource, TTarget>(this TSource source, string name = null) where TSource : class where TTarget : class
+        {
+            if (source == null)
+            {
+                return null;
+            }
+
+            if (!_initialized)
+            {
+                Initialize();
+            }
+            TTarget result = null;
+            MapperConfiguration<TSource, TTarget> mapper = GetMapper<TSource, TTarget>(name);
+            Func<TSource, TTarget> query = mapper.GetFuncDelegate();
+            if (query != null)
+            {
+                result = query(source);
+                // 映射后执行的操作
+                mapper.ExecuteAfterActions(source, result);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// 将指定的源映射到目标。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="source">源对象</param>
+        /// <param name="target">目标对象</param>
+        /// <param name="name">别名</param>
+        public static void Map<TSource, TTarget>(this TSource source, TTarget target, string name = null) where TSource : class where TTarget : class
+        {
+            if (!_initialized)
+            {
+                Initialize();
+            }
+            TTarget result = null;
+            MapperConfiguration<TSource, TTarget> mapper = GetMapper<TSource, TTarget>(name);
+            Action<TSource, TTarget> query = mapper.GetDelegateForExistingTarget() as Action<TSource, TTarget>;
+            if (query != null)
+            {
+                query(source, target);
+                // 映射后执行的操作
+                mapper.ExecuteAfterActions(source, result);
+            }
+        }
+
+        /// <summary>
+        /// 获取查询表达式树
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <returns></returns>
+        public static Expression<Func<TSource, TTarget>> GetQueryExpression<TSource, TTarget>() where TSource : class where TTarget : class
+        {
+            return GetMapper<TSource, TTarget>().GetLambdaExpression();
+        }
+
+        /// <summary>
+        /// 创建mapper对象
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <returns></returns>
+        public static MapperConfiguration<TSource, TTarget> CreateMap<TSource, TTarget>(string name = null) where TSource : class where TTarget : class
+        {
+            MapperConfigurationBase map = MapperConfigurationCollectionContainer.Instance.Find(typeof(TSource), typeof(TTarget), name);
+            if (map == null)
+            {
+                string finalName = string.IsNullOrEmpty(name) ? "s" + MapperConfigurationCollectionContainer.Instance.Count.ToString() : name;
+                map = new MapperConfiguration<TSource, TTarget>(finalName);
+                MapperConfigurationCollectionContainer.Instance.Add(map);
+            }
+            return map as MapperConfiguration<TSource, TTarget>;
+        }
+
+        /// <summary>
+        /// 表示使用的依赖注入服务
+        /// </summary>
+        /// <param name="constructor">构造函数委托</param>
+        public static void ConstructServicesUsing(Func<Type, object> constructor)
+        {
+            _constructorFunc = constructor;
+        }
+
+        /// <summary>
+        /// 重置mapper
+        /// </summary>
+        public static void Reset()
+        {
+            MapperConfigurationCollectionContainer.Instance.Clear();
+        }
+
+        /// <summary>
+        /// 获取mapper实例
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TDest">目标类型</typeparam>
+        /// <param name="name">别名</param>
+        /// <returns></returns>
+        public static MapperConfiguration<TSource, TDest> GetMapper<TSource, TDest>(string name = null) where TSource : class where TDest : class
+        {
+            return GetMapper(typeof(TSource), typeof(TDest), name) as MapperConfiguration<TSource, TDest>;
+        }
+
+        /// <summary>
+        /// 初始化mapper
+        /// </summary>
+        public static void Initialize()
+        {
+            MapperConfigurationCollectionContainer configRegister = MapperConfigurationCollectionContainer.Instance;
+            foreach (var t in configRegister)
+            {
+                t.Initialize(_constructorFunc);
+            }
+            _initialized = true;
+        }
+
+        /// <summary>
+        /// 获取mapper的委托
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TDest">目标类型</typeparam>
+        /// <returns></returns>
+        public static Func<TSource, TDest> GetQuery<TSource, TDest>() where TSource : class where TDest : class
+        {
+            return GetMapper<TSource, TDest>().GetFuncDelegate();
+        }
+
+        /// <summary>
+        /// 获取未映射的属性
+        /// </summary>
+        public static PropertiesNotMapped GetPropertiesNotMapped<TSource, TDest>(string name = null) where TSource : class where TDest : class
+        {
+            var mapper = GetMapper<TSource, TDest>(name);
+            return mapper.GetPropertiesNotMapped();
+        }
+
+        internal static MapperConfigurationBase GetMapper(Type tSource, Type tDest, string name = null)
+        {
+            MapperConfigurationBase mapConfig = MapperConfigurationCollectionContainer.Instance.Find(tSource, tDest, name);
+            if (mapConfig == null)
+            {
+                throw new NoFoundMapperException(tSource, tDest);
+            }
+
+            return mapConfig;
+        }
+    }
+}

+ 77 - 0
Masuit.Tools.Core/Mapping/Extensions/ExpressionExtentions.cs

@@ -0,0 +1,77 @@
+using Masuit.Tools.Mapping.Visitor;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Extensions
+{
+    /// <summary>
+    ///表达式树扩展
+    /// </summary>
+    public static class ExpressionExtentions
+    {
+        /// <summary>
+        /// 转换
+        /// </summary>
+        /// <typeparam name="TFrom">源类型</typeparam>
+        /// <param name="from">来源</param>
+        /// <param name="toType">目标类型</param>
+        /// <returns></returns>
+        public static Expression ConvertTo<TFrom>(this Expression<Func<TFrom, object>> from, Type toType)
+        {
+            return ConvertImpl(from, toType);
+        }
+
+        /// <summary>
+        /// 转换
+        /// </summary>
+        /// <typeparam name="TFrom">源类型</typeparam>
+        /// <param name="from">来源</param>
+        /// <param name="toType">目标类型</param>
+        /// <returns></returns>
+        public static Expression ConvertTo<TFrom>(this Expression<Func<TFrom, bool>> from, Type toType)
+        {
+            return ConvertImpl(from, toType);
+        }
+
+        /// <summary>
+        /// 转换Lambda表达式树
+        /// </summary>
+        /// <typeparam name="TFrom">源类型</typeparam>
+        /// <typeparam name="TTo">目标类型</typeparam>
+        /// <param name="from">来源</param>
+        /// <returns></returns>
+        public static Expression ConvertTo<TFrom, TTo>(this Expression<Func<TFrom, object>> from)
+        {
+            return ConvertImpl(from, typeof(TTo));
+        }
+
+        /// <summary>
+        /// 转换表达式树
+        /// </summary>
+        /// <typeparam name="TFrom">源类型的表达式树</typeparam>
+        /// <typeparam name="TTo">目标类型的表达式树</typeparam>
+        /// <param name="from">源类型的表达式树</param>
+        /// <returns>表达式转换或如果没有找到映射原始表达式。</returns>
+        public static Expression<Func<TTo, bool>> ConvertTo<TFrom, TTo>(this Expression<Func<TFrom, bool>> from)
+        {
+            return (Expression<Func<TTo, bool>>)ConvertImpl(from, typeof(TTo));
+        }
+
+        private static Expression ConvertImpl<TFrom>(Expression<TFrom> from, Type toType) where TFrom : class
+        {
+            //  重新映射不同类型的所有参数
+            Dictionary<Expression, Expression> parameterMap = new Dictionary<Expression, Expression>();
+            ParameterExpression[] newParams = new ParameterExpression[from.Parameters.Count];
+            for (int i = 0; i < newParams.Length; i++)
+            {
+                newParams[i] = Expression.Parameter(toType, from.Parameters[i].Name);
+                parameterMap[from.Parameters[i]] = newParams[i];
+            }
+
+            // 重新构建表达式树
+            var body = new ConverterExpressionVisitor(parameterMap, toType).Visit(from.Body);
+            return Expression.Lambda(body, newParams);
+        }
+    }
+}

+ 124 - 0
Masuit.Tools.Core/Mapping/Extensions/QueryableExtentions.cs

@@ -0,0 +1,124 @@
+using Masuit.Tools.Mapping.Core;
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Extensions
+{
+    /// <summary>
+    /// IQueryable的扩展
+    /// </summary>
+    public static class QueryableExtentions
+    {
+        /// <summary>
+        /// 根据键按升序对序列的元素进行排序。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="sortedPropertyDestName">目标属性的名称</param>
+        /// <returns></returns>
+        public static IOrderedQueryable<TSource> OrderBy<TSource, TTarget>(this IQueryable<TSource> query, string sortedPropertyDestName) where TSource : class where TTarget : class
+        {
+            // 没有使用MethodBase.GetCurrentMethod().Name,因为效率不高
+            return CreateSortedMethodCall<TSource, TTarget, IOrderedQueryable<TSource>>(query, "OrderBy", sortedPropertyDestName);
+        }
+
+        /// <summary>
+        /// 根据键按降序对序列的元素进行排序。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="sortedPropertyDestName">目标属性的名称</param>
+        /// <returns></returns>
+        public static IOrderedQueryable<TSource> OrderByDescending<TSource, TTarget>(this IQueryable<TSource> query, string sortedPropertyDestName) where TSource : class where TTarget : class
+        {
+            return CreateSortedMethodCall<TSource, TTarget, IOrderedQueryable<TSource>>(query, "OrderByDescending", sortedPropertyDestName);
+        }
+
+        /// <summary>
+        ///  根据键按升序对序列的元素进行排序。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="sortedPropertyDestName">目标属性的名称</param>
+        public static IOrderedQueryable<TSource> ThenBy<TSource, TTarget>(this IQueryable<TSource> query, string sortedPropertyDestName) where TSource : class where TTarget : class
+        {
+            return CreateSortedMethodCall<TSource, TTarget, IOrderedQueryable<TSource>>(query, "ThenBy", sortedPropertyDestName);
+        }
+
+        /// <summary>
+        /// 根据键按降序对序列的元素进行排序。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="sortedPropertyDestName">目标属性的名称</param>
+        public static IOrderedQueryable<TSource> ThenByDescending<TSource, TTarget>(this IQueryable<TSource> query, string sortedPropertyDestName) where TSource : class where TTarget : class
+        {
+            return CreateSortedMethodCall<TSource, TTarget, IOrderedQueryable<TSource>>(query, "ThenByDescending", sortedPropertyDestName);
+        }
+
+        /// <summary>
+        /// 通过合并目标对象将序列的每个元素投影到新表单中。
+        /// </summary>
+        /// <typeparam name="TSource">源类型.</typeparam>
+        /// <typeparam name="TTarget">目标类型.</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        public static IQueryable<TTarget> Select<TSource, TTarget>(this IQueryable<TSource> query) where TSource : class where TTarget : class
+        {
+            return GetSelect<TSource, TTarget>(query, null);
+        }
+
+        /// <summary>
+        /// 通过合并目标对象将序列的每个元素投影到新表单中。
+        /// </summary>
+        /// <typeparam name="TSource">源类型.</typeparam>
+        /// <typeparam name="TTarget">目标类型.</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="mapperName">mapper别名</param>
+        /// <returns></returns>
+        public static IQueryable<TTarget> Select<TSource, TTarget>(this IQueryable<TSource> query, string mapperName) where TSource : class where TTarget : class
+        {
+            return GetSelect<TSource, TTarget>(query, mapperName);
+        }
+
+        /// <summary>
+        /// 根据谓词过滤一系列值。
+        /// </summary>
+        /// <typeparam name="TSource">源类型</typeparam>
+        /// <typeparam name="TTarget">目标类型</typeparam>
+        /// <param name="query">分类化的序列值</param>
+        /// <param name="predicate">用于根据条件测试每个元素的功能。</param>
+        /// <returns></returns>
+        public static IQueryable<TTarget> Where<TSource, TTarget>(this IQueryable<TTarget> query, Expression<Func<TSource, bool>> predicate)
+        {
+            return Queryable.Where(query, predicate.ConvertTo<TSource, TTarget>());
+        }
+
+        private static TQueryable CreateSortedMethodCall<TSource, TTarget, TQueryable>(IQueryable<TSource> query, string methodName, string sortedPropertySourceName) where TSource : class where TTarget : class where TQueryable : class, IQueryable<TSource>
+        {
+            MapperConfiguration<TSource, TTarget> mapper = ExpressionMapper.GetMapper<TSource, TTarget>();
+            var prop = mapper.GetLambdaDest(sortedPropertySourceName);
+            var lambda = mapper.GetSortedExpression(sortedPropertySourceName);
+            MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName, new Type[]
+            {
+                typeof(TSource),
+                prop.Type
+            }, query.Expression, Expression.Quote(lambda));
+            return query.Provider.CreateQuery<TSource>(resultExp) as TQueryable;
+        }
+
+        private static IQueryable<TTarget> GetSelect<TSource, TTarget>(IQueryable<TSource> query, string mapperName) where TSource : class where TTarget : class
+        {
+            // 不需要mapper
+            if (typeof(TSource) == typeof(TTarget))
+            {
+                return (IQueryable<TTarget>)query;
+            }
+            return query.Select(ExpressionMapper.GetMapper<TSource, TTarget>(mapperName).GetLambdaExpression());
+        }
+    }
+}

+ 34 - 0
Masuit.Tools.Core/Mapping/Helper/MapperHelper.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Helper
+{
+    /// <summary>
+    /// mapper帮助类
+    /// </summary>
+    internal static class MapperHelper
+    {
+        /// <summary>
+        /// 获取类型的默认值。
+        /// </summary>
+        /// <param name="typeObject">对象类型</param>
+        internal static object GetDefaultValue(Type typeObject)
+        {
+            object defaultValue = null;
+            // 对于值类型(例如Integer),必须将对象实例化为具有其默认值。
+            if (typeObject.BaseType == typeof(ValueType))
+            {
+                NewExpression exp = Expression.New(typeObject);
+                LambdaExpression lambda = Expression.Lambda(exp);
+                Delegate constructor = lambda.Compile();
+                defaultValue = constructor.DynamicInvoke();
+            }
+            if (typeObject.IsEnum)
+            {
+                defaultValue = Enum.Parse(typeObject, Enum.GetNames(typeObject)[0]);
+            }
+
+            return defaultValue;
+        }
+    }
+}

+ 64 - 0
Masuit.Tools.Core/Mapping/Helper/TypeSystem.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+
+namespace Masuit.Tools.Mapping.Helper
+{
+    internal static class TypeSystem
+    {
+        internal static Type GetElementType(Type seqType)
+        {
+            Type ienum = FindIEnumerable(seqType);
+            if (ienum == null)
+            {
+                return seqType;
+            }
+
+            return ienum.GetGenericArguments()[0];
+        }
+
+        private static Type FindIEnumerable(Type seqType)
+        {
+            if (seqType == null || seqType == typeof(string))
+            {
+                return null;
+            }
+
+            if (seqType.IsArray)
+            {
+                return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
+            }
+
+            if (seqType.IsGenericType)
+            {
+                foreach (Type arg in seqType.GetGenericArguments())
+                {
+                    Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
+                    if (ienum.IsAssignableFrom(seqType))
+                    {
+                        return ienum;
+                    }
+                }
+            }
+
+            Type[] ifaces = seqType.GetInterfaces();
+
+            if (ifaces != null && ifaces.Length > 0)
+            {
+                foreach (Type iface in ifaces)
+                {
+                    Type ienum = FindIEnumerable(iface);
+                    if (ienum != null)
+                    {
+                        return ienum;
+                    }
+                }
+            }
+
+            if (seqType.BaseType != null && seqType.BaseType != typeof(object))
+            {
+                return FindIEnumerable(seqType.BaseType);
+            }
+            return null;
+        }
+    }
+}

+ 26 - 0
Masuit.Tools.Core/Mapping/Visitor/ChangParameterExpressionVisitor.cs

@@ -0,0 +1,26 @@
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Visitor
+{
+    internal class ChangParameterExpressionVisitor : ExpressionVisitor
+    {
+        private readonly Expression[] _parameter;
+        internal ChangParameterExpressionVisitor(params Expression[] parameter)
+        {
+            _parameter = parameter;
+        }
+
+        protected override Expression VisitParameter(ParameterExpression node)
+        {
+            if (node != null)
+            {
+                Expression returnParameter = _parameter.FirstOrDefault(x => x.Type == node.Type);
+                if (returnParameter != null)
+                    return returnParameter;
+            }
+            return node;
+        }
+
+    }
+}

+ 109 - 0
Masuit.Tools.Core/Mapping/Visitor/ConverterExpressionVisitor.cs

@@ -0,0 +1,109 @@
+using Masuit.Tools.Mapping.Core;
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Visitor
+{
+    /// <summary>
+    /// 将表达式从源转换为目标的访问者表达式
+    /// </summary>
+    public class ConverterExpressionVisitor : ExpressionVisitor
+    {
+        private readonly Dictionary<Expression, Expression> _parameterMap;
+        private readonly Type _destinationType;
+        private MapperConfigurationBase _mapper;
+
+
+        public ConverterExpressionVisitor(Dictionary<Expression, Expression> parameterMap, Type typeDestination)
+        {
+            _parameterMap = parameterMap;
+            _destinationType = typeDestination;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="node">访问表达式树</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        protected override Expression VisitParameter(ParameterExpression node)
+        {
+            if (!_parameterMap.TryGetValue(node, out var found))
+            {
+                found = Expression.Parameter(_destinationType, "dest");
+            }
+
+            return found;
+        }
+
+        /// <summary>
+        /// 将表达式分布在此类中更专业的访问方法之一。
+        /// </summary>
+        /// <param name="node">访问表达式树</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        public override Expression Visit(Expression node)
+        {
+            if (node != null)
+            {
+                Expression expression;
+                switch (node.NodeType)
+                {
+                    case ExpressionType.Lambda:
+                        expression = base.Visit((node as LambdaExpression).Body);
+                        break;
+                    default:
+                        expression = base.Visit(node);
+                        break;
+                }
+                return expression;
+            }
+            return node;
+        }
+
+        /// <summary>
+        /// 访问子表达式树
+        /// </summary>
+        /// <param name="node">访问表达式树</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        protected override Expression VisitMember(MemberExpression node)
+        {
+            var expr = Visit(node.Expression);
+            if (expr != null && expr.Type != node.Type)
+            {
+                if (_mapper == null)
+                {
+                    _mapper = ExpressionMapper.GetMapper(node.Member.DeclaringType, _destinationType);
+                }
+                Expression expDest;
+                // 认为原始类是简单属性(不是子对象)。
+                if (!expr.Type.IsValueType && expr.Type != typeof(string) && expr.NodeType != ExpressionType.Parameter && expr.NodeType != ExpressionType.Constant)
+                {
+                    var subExp = ExpressionMapper.GetMapper(node.Member.DeclaringType, expr.Type);
+                    expDest = subExp.GetLambdaDest(node.Member.Name);
+                    return AnalyseDestExpression(expr, expDest);
+                }
+                expDest = _mapper.GetLambdaDest(node.Member.Name);
+                if (expDest != null)
+                {
+                    return AnalyseDestExpression(expr, expDest);
+                }
+            }
+            return base.VisitMember(node);
+        }
+
+        private Expression AnalyseDestExpression(Expression expr, Expression expDest)
+        {
+            if (expDest.NodeType == ExpressionType.MemberAccess)
+            {
+                return Expression.MakeMemberAccess(expr, (expDest as MemberExpression).Member);
+            }
+            return base.Visit(expDest);
+        }
+    }
+}

+ 203 - 0
Masuit.Tools.Core/Mapping/Visitor/MapperExpressionVisitor.cs

@@ -0,0 +1,203 @@
+using Masuit.Tools.Mapping.Helper;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace Masuit.Tools.Mapping.Visitor
+{
+    public class MapperExpressionVisitor : ExpressionVisitor
+    {
+        private bool _checkNull;
+        readonly Stack<MemberExpression> _membersToCheck;
+
+        internal Expression Parameter { get; }
+
+        public MapperExpressionVisitor(Expression paramClassSource)
+        {
+            Parameter = paramClassSource;
+            _membersToCheck = new Stack<MemberExpression>();
+        }
+
+        /// <summary>
+        /// 将表达式分布在此类中更专一的访问方法之一。
+        /// </summary>
+        /// <param name="node">访问表达式树</param>
+        /// <param name="checkIfNullity">检查null值</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        public Expression Visit(Expression node, bool checkIfNullity = false)
+        {
+            _checkNull = checkIfNullity;
+            if (node == null)
+            {
+                return node;
+            }
+
+            if (_checkNull)
+            {
+                Expression result;
+                switch (node.NodeType)
+                {
+                    case ExpressionType.MemberAccess:
+                        result = VisitMember(node as MemberExpression);
+                        break;
+                    case ExpressionType.Parameter:
+                        result = VisitParameter(node as ParameterExpression);
+                        break;
+                    case ExpressionType.Convert:
+                        result = VisitMember((node as UnaryExpression).Operand as MemberExpression);
+                        break;
+                    case ExpressionType.Lambda:
+                        LambdaExpression lambda = ((LambdaExpression)node);
+                        // 子表达式树
+                        if (lambda.Body.NodeType != ExpressionType.Lambda)
+                        {
+                            result = Visit(lambda.Body);
+                        }
+                        else
+                        {
+                            return lambda;
+                        }
+
+                        break;
+                    default:
+                        result = base.Visit(node);
+                        break;
+                }
+
+                bool isFirst = true;
+                Expression previousExpression = null;
+                if (_membersToCheck.Count > 1)
+                {
+                    // 在分配值之前测试所有子对象。例如:source.SubClass.SubClass2.MyProperty。是哪个会给:
+                    // source.SubClass!= null? source.SubClass.SubClass2!= null? source.SubClass.SubClass2.MyProperty:DefaultValueOfProperty:DefaultValueOfProperty
+                    foreach (MemberExpression item in _membersToCheck)
+                    {
+                        if (!isFirst) // 不要测试该属性的值。
+                        {
+                            object defaultValue = MapperHelper.GetDefaultValue(item.Type);
+
+                            // 创建默认值的验证。
+                            Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
+                            Expression conditional = null;
+                            // 它创建了包含上述条件的条件。
+                            if (previousExpression != null)
+                            {
+                                object defaultPreviousValue = MapperHelper.GetDefaultValue(previousExpression.Type);
+                                conditional = Expression.Condition(notDefaultValue, previousExpression, Expression.Constant(defaultPreviousValue, previousExpression.Type));
+                            }
+
+                            // 它会影响新创建的条件,这些条件将成为之前的条件。
+                            previousExpression = conditional;
+                        }
+                        else // 属性
+                        {
+                            previousExpression = item;
+                            isFirst = false;
+                        }
+                    }
+
+                    return previousExpression;
+                }
+
+                // 不需要递归的元素。
+                if (_membersToCheck.Count == 1)
+                {
+                    var item = _membersToCheck.Peek();
+                    object defaultValue = MapperHelper.GetDefaultValue(item.Type);
+                    // 创建默认值的验证。
+                    Expression notDefaultValue = Expression.NotEqual(item, Expression.Constant(defaultValue, item.Type));
+                    Expression conditional = Expression.Condition(notDefaultValue, item, Expression.Constant(defaultValue, item.Type));
+
+                    return conditional;
+                }
+
+                return result;
+            }
+
+            // 默认返回(更改参数),删除lambda表达式的验证。
+            if ((node.NodeType == ExpressionType.Lambda))
+            {
+                LambdaExpression lambda = ((LambdaExpression)node);
+                // 子表达式树
+                if (lambda.Body.NodeType != ExpressionType.Call)
+                {
+                    return base.Visit(lambda.Body);
+                }
+
+                return lambda;
+            }
+
+            return base.Visit(node);
+        }
+
+        /// <summary>
+        /// 访问表达式树
+        /// </summary>
+        /// <param name="node">表达式树节点</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        protected override Expression VisitParameter(ParameterExpression node)
+        {
+            return Parameter;
+        }
+
+        /// <summary>
+        /// 访问子表达式树
+        /// </summary>
+        /// <param name="node">表达式树节点</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        protected override Expression VisitMember(MemberExpression node)
+        {
+            if (node == null)
+            {
+                return node;
+            }
+
+            if (node.Member.ReflectedType != Parameter.Type)
+            {
+                var exp = Visit(node.Expression);
+                return Expression.MakeMemberAccess(exp, node.Member);
+            }
+
+            MemberExpression memberAccessExpression = (MemberExpression)base.VisitMember(node);
+
+            // 稍后处理
+            if (memberAccessExpression != null && _checkNull)
+            {
+                // 如果最后一个成员是第一次访问,那么每次都得回去,当前的插入成员位于列表的第一行以更改顺序。
+                _membersToCheck.Push(memberAccessExpression);
+            }
+
+            return memberAccessExpression;
+        }
+
+        /// <summary>
+        ///  访问子表达式树
+        /// </summary>
+        /// <param name="node">表达式树节点</param>
+        /// <returns>
+        /// 改变表达式,如果它或它的任何子表达式被修改; 否则,返回原始表达式。
+        /// </returns>
+        protected override Expression VisitUnary(UnaryExpression node)
+        {
+            if (node != null)
+            {
+                if (node.Operand.NodeType == ExpressionType.MemberAccess)
+                {
+                    return VisitMember(node.Operand as MemberExpression);
+                }
+
+                if (node.NodeType == ExpressionType.Convert)
+                {
+                    return Visit(node.Operand);
+                }
+            }
+
+            return node;
+        }
+    }
+}

+ 35 - 0
Masuit.Tools.Core/Mapping/Visitor/PropertiesVisitor.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Masuit.Tools.Mapping.Visitor
+{
+    internal class PropertiesVisitor : ExpressionVisitor
+    {
+        private readonly List<PropertyInfo> _propertiesOfExpression;
+
+        private readonly Type _typeReference;
+
+        internal PropertiesVisitor(Type typeReference)
+        {
+            _typeReference = typeReference;
+            _propertiesOfExpression = new List<PropertyInfo>();
+        }
+
+        protected override Expression VisitMember(MemberExpression node)
+        {
+            if (_typeReference == node.Member.DeclaringType)
+            {
+                _propertiesOfExpression.Add(node.Member as PropertyInfo);
+            }
+            return base.VisitMember(node);
+        }
+
+        internal List<PropertyInfo> GetProperties(Expression expression)
+        {
+            Visit(expression);
+            return _propertiesOfExpression;
+        }
+    }
+}