ExpressionMapper(对象映射)

 性能接近硬编码,推荐使用

    /// <summary>
    /// 高性能对象映射
    /// </summary>
    /// <typeparam name="TSource"></typeparam>
    /// <typeparam name="TTarget"></typeparam>
    public static class ExpressionMapper<TSource, TTarget> where TSource : class where TTarget : class
    {
        private static readonly ConcurrentDictionary<string, Func<TSource, TTarget>> FUNC_CACHE = new ConcurrentDictionary<string, Func<TSource, TTarget>>();
        private static readonly ConcurrentDictionary<Type, PropertyInfo[]> TYPE_CACHE = new ConcurrentDictionary<Type, PropertyInfo[]>();

        /// <summary>
        /// 对象映射
        /// </summary>
        /// <returns></returns>
        public static TTarget Trans(TSource source)
        {
            if (source == null) { return null; }
            var sourceType = typeof(TSource);
            var targetType = typeof(TTarget);
            string cacheName = $"cache_{typeof(TSource).FullName}_{typeof(TTarget).FullName}";
            Func<TSource, TTarget> func = FUNC_CACHE.GetOrAdd(cacheName, key =>
            {
                //构造 p=>
                var parameterExpression = Expression.Parameter(sourceType, "p");

                var memberBindingList = new List<MemberBinding>();
                foreach (var sourceItem in sourceType.GetProperties())
                {
                    var targetItem = targetType.GetProperty(sourceItem.Name);

                    if (targetItem == null || sourceItem.PropertyType != targetItem.PropertyType || !targetItem.CanWrite)
                    { continue; }

                    var property = Expression.Property(parameterExpression, sourceItem);
                    var memberBinding = Expression.Bind(targetItem, property);
                    memberBindingList.Add(memberBinding);
                }
                var memberInitExpression = Expression.MemberInit(Expression.New(targetType), memberBindingList);

                var lambda = Expression.Lambda<Func<TSource, TTarget>>(memberInitExpression, parameterExpression);

                Console.WriteLine(lambda);
                return lambda.Compile();
            });
            return func(source);
        }
        /// <summary>
        /// 列表映射
        /// </summary>
        /// <param name="tSourceList"></param>
        /// <returns></returns>
        public static List<TTarget> Trans(IEnumerable<TSource> tSourceList)
        {
            List<TTarget> outList = new List<TTarget>();
            if (tSourceList != null)
            {
                foreach (var inItem in tSourceList)
                {
                    outList.Add(Trans(inItem));
                }
            }

            return outList;
        }

        /// <summary>
        /// 更新现有对象,指定要更新的属性
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void TryUpdateModel(TSource source, TTarget target, params Expression<Func<TSource, object>>[] includeExps)
        {
            string[] includePropertyNames = includeExps != null ? GetPropertyNames<TSource>(includeExps) : null;
            TryUpdateModel(source, target, includePropertyNames);
        }
        /// <summary>
        /// 更新现有对象,指定要更新的属性
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void TryUpdateModel(TSource source, TTarget target, params string[] includeProperties)
        {
            //TTarget tOutNew = Trans(source);
            if (target != null)
            {
                var inProperties = GetProperties(typeof(TSource));
                var outProperties = GetProperties(typeof(TTarget));
                PropertyInfo inProp = null;
                object inValue = null;
                foreach (var outProp in outProperties)
                {
                    if (includeProperties?.Length > 0 && !includeProperties.Contains(outProp.Name))
                    {
                        continue;
                    }
                    inProp = inProperties.FirstOrDefault(p => p.Name.Equals(outProp.Name, StringComparison.CurrentCultureIgnoreCase));
                    inValue = inProp.GetValue(source);

                    if (inValue != null)
                    {
                        outProp.SetValue(target, inValue);
                    }
                }
            }
        }
        /// <summary>
        /// 更新现有对象,指定要排除的属性
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void TryUpdateModelEx(TSource source, TTarget target, params Expression<Func<TSource, object>>[] excludeExps)
        {
            string[] excludePropertyNames = excludeExps != null ? GetPropertyNames<TSource>(excludeExps) : null;
            TryUpdateModelEx(source, target, excludePropertyNames);
        }
        /// <summary>
        /// 更新现有对象,指定要排除的属性
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public static void TryUpdateModelEx(TSource source, TTarget target, params string[] excludePropertyNames)
        {
            //TTarget tOutNew = Trans(source);
            if (target != null)
            {
                var inProperties = GetProperties(typeof(TSource));
                var outProperties = GetProperties(typeof(TTarget));
                PropertyInfo inProp = null;
                object inValue = null;
                foreach (var outProp in outProperties)
                {
                    if (excludePropertyNames?.Length > 0 && excludePropertyNames.Contains(outProp.Name))
                    {
                        continue;
                    }
                    inProp = inProperties.FirstOrDefault(p => p.Name.Equals(outProp.Name, StringComparison.CurrentCultureIgnoreCase));
                    if (inProp != null)
                    {
                        inValue = inProp.GetValue(source);
                        if (inValue != null)
                        {
                            outProp.SetValue(target, inValue);
                        }
                    }
                }

            }
        }
        private static PropertyInfo[] GetProperties(Type t)
        {
            return TYPE_CACHE.GetOrAdd(t, (k) =>
            {
                return t.GetProperties();
            });
        }
        private static string[] GetPropertyNames<T>(params Expression<Func<T, object>>[] exps)
        {
            string[] props = new string[exps.Length];
            for (int i = 0; i < exps.Length; i++)
            {
                props[i] = GetPropertyName(exps[i]);
            }
            return props;
        }
        private static readonly ConcurrentDictionary<Type, string> EXPRESSION_CACHE = new ConcurrentDictionary<Type, string>();
        private static string GetPropertyName<T>(Expression<Func<T, object>> expr)
        {
            return EXPRESSION_CACHE.GetOrAdd(expr.GetType(), t =>
            {
                string rtn = null;
                if (expr.Body is UnaryExpression)
                {
                    rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;
                }
                else if (expr.Body is MemberExpression)
                {
                    rtn = ((MemberExpression)expr.Body).Member.Name;
                }
                else if (expr.Body is ParameterExpression)
                {
                    rtn = ((ParameterExpression)expr.Body).Type.Name;
                }
                return rtn;
            });

        }
    }

客户端:

//1
var peopleDTO1 = ExpressionMapper<People, PeopleDTO>.Trans(p);

//2绑定
var peopleDTO2 = new PeopleDTO() {  Name="",Birthday = DateTime.Now.AddYears(1) };
ExpressionMapper<People, PeopleDTO>.TryUpdateModel(p, peopleDTO2,nameof(p.Name));

 参考:https://www.cnblogs.com/castyuan/p/9324088.html

原文地址:https://www.cnblogs.com/fanfan-90/p/12828967.html