• 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

  • 相关阅读:
    TypeError: write() argument must be str, not bytes报错
    md5加密报错解决方法(TypeError: Unicode-objects must be encoded before hashing)
    认识requests库,以及安装方法
    python开发必备pycharm专业版破解方法
    接口测试面试题
    jmeter断言
    大顶堆和小顶堆模版
    快速幂带取余模版
    二叉树的前中后序遍历的递归与非递归算法模版
    KMP算法模版
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12828967.html
Copyright © 2020-2023  润新知