SafeClone.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace Ant.Core.Utils
  8. {
  9. /// <summary>
  10. /// 高效实体转换(浅拷贝)(反射+表达式目录树+静态缓存 方式)
  11. /// </summary>
  12. /// <typeparam name="TIn"></typeparam>
  13. /// <typeparam name="TOut"></typeparam>
  14. public static class SafeClone<TIn, TOut>
  15. {
  16. private static readonly Func<TIn, TOut> cache = GetFunc();
  17. private static Func<TIn, TOut> GetFunc()
  18. {
  19. ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
  20. List<MemberBinding> memberBindingList = new List<MemberBinding>();
  21. foreach (var item in typeof(TOut).GetProperties())
  22. {
  23. if (!item.CanWrite) continue;
  24. var tInProperty = typeof(TIn).GetProperties().FirstOrDefault(x => x.Name == item.Name);
  25. if (tInProperty != null && tInProperty.PropertyType == item.PropertyType)
  26. {
  27. MemberExpression property = Expression.Property(parameterExpression, tInProperty);
  28. MemberBinding memberBinding = Expression.Bind(item, property);
  29. memberBindingList.Add(memberBinding);
  30. }
  31. }
  32. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
  33. Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });
  34. return lambda.Compile();
  35. }
  36. public static TOut Trans(TIn tIn)
  37. {
  38. return cache(tIn);
  39. }
  40. }
  41. }