从本章节开始,所有的知识点只记录核心重点, 不做基础介绍,看知识点性质,偏向于理论则重理论

1.表达式目录树Expression

  1. //1. 先看看委托 拉姆达表达式其实是作为委托的一个参数,本质是一个方法(匿名方法)
  2. Func<int, int, int> func = (m, n) =>
  3. {
  4. int i = 0;
  5. return m * n + 2;
  6. };
  7. //2.再看表达式目录树, 其数据结构--就像对一个计算做了一个精确的描述,展开之后发现,分为左边,右边,每个元素都可以把值都获取出来,二叉树
  8. Expression<Func<int, int, int>> exp = (m, n) => m * n + 2;
  9. //3.表达式目录树可以通过compile 转换成一个委托
  10. var erpPlu= exp.Compile();
  11. //4 注意:表达式目录树只能有一行;
  12. Expression<Func<int, int, int>> exp1 = (m, n) =>
  13. {
  14. return m * n + 2;
  15. };
  16. //5. Invoke(执行) 表达式目录树:语法树,或者说是一种数据结构
  17. int iResult1 = func.Invoke(12, 23);
  18. int iResult2 = exp.Compile().Invoke(12, 23);

2.动态拼装表达式目录树

  1. //1. 目标是拼装如下表达式,首先反编译后看看大概代码,然后从右边往后拆分替换,
  2. Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");
  3. ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
  4. FieldInfo idfield = typeof(People).GetField("Id");
  5. var idExp = Expression.Field(parameterExpression, idfield);
  6. //int i = 0;
  7. //i.ToString();
  8. MethodInfo toString = typeof(int).GetMethod("ToString", new Type[0]);
  9. //Expression.Call()调用方法
  10. var toStringExp = Expression.Call(idExp, toString, Array.Empty<Expression>());
  11. var Equals = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
  12. Expression expressionConstant5 = Expression.Constant("5", typeof(string));
  13. var equalsExp = Expression.Call(toStringExp, Equals, new Expression[]
  14. {
  15. expressionConstant5
  16. });
  17. Expression<Func<People, bool>> expression = Expression.Lambda<Func<People, bool>>(equalsExp, new ParameterExpression[]
  18. {
  19. parameterExpression
  20. });
  21. //转成委托
  22. Func<People, bool> func = expression.Compile();
  23. //调用
  24. var bResult = func.Invoke(new People()
  25. {
  26. Id = 5,
  27. Name = "海贝"
  28. });
  29. //测试
  30. new List<People>().AsQueryable().Where(expression);

3.基于Expression的扩展应用

  1. 现有一需求 people 转化成 peoplecopy
  2. {
  3. People people = new People()
  4. {
  5. Id = 11,
  6. Name = "张三",
  7. Age = 31
  8. };
  9. //不能转换,因为没有父子级关系;
  10. PeopleCopy copy = (PeopleCopy)people;
  11. //方式1 :硬编码性能最高,扩展性不好,
  12. PeopleCopy peopleCopy = new PeopleCopy()
  13. {
  14. Id = people.Id,
  15. Name = people.Name,
  16. Age = people.Age
  17. };
  18. //方式2:反射,性能问题
  19. PeopleCopy peopleCopy1 = ReflectionMapper.Trans<People, PeopleCopy>(people);
  20. public class ReflectionMapper
  21. {
  22. /// <summary>
  23. /// 反射
  24. /// </summary>
  25. /// <typeparam name="TIn"></typeparam>
  26. /// <typeparam name="TOut"></typeparam>
  27. /// <param name="tIn"></param>
  28. /// <returns></returns>
  29. public static TOut Trans<TIn, TOut>(TIn tIn)
  30. {
  31. TOut tOut = Activator.CreateInstance<TOut>();
  32. foreach (var itemOut in tOut.GetType().GetProperties())
  33. {
  34. var propIn = tIn.GetType().GetProperty(itemOut.Name);
  35. itemOut.SetValue(tOut, propIn.GetValue(tIn));
  36. }
  37. foreach (var itemOut in tOut.GetType().GetFields())
  38. {
  39. var fieldIn = tIn.GetType().GetField(itemOut.Name);
  40. itemOut.SetValue(tOut, fieldIn.GetValue(tIn));
  41. }
  42. return tOut;
  43. }
  44. }
  45. //方式3:序列化反序列化,性能问题;
  46. PeopleCopy peopleCopy2 = SerializeMapper.Trans<People, PeopleCopy>(people);
  47. /// <summary>
  48. /// 使用第三方序列化反序列化工具
  49. /// 还有automapper
  50. /// </summary>
  51. public class SerializeMapper
  52. {
  53. /// <summary>
  54. /// 序列化反序列化方式
  55. /// </summary>
  56. /// <typeparam name="TIn"></typeparam>
  57. /// <typeparam name="TOut"></typeparam>
  58. public static TOut Trans<TIn, TOut>(TIn tIn)
  59. {
  60. return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(tIn));
  61. }
  62. }
  63. }
  1. //方式4:生成表达式目录树 字典缓存
  2. PeopleCopy peopleCopy4 = ExpressionMapper.Trans<People, PeopleCopy>(people);
  3. /// <summary>
  4. /// 生成表达式目录树 缓存
  5. ///想办法去动态拼装这个委托,然后缓存下委托,后面再次转换时就没有性能损耗了
  6. /// </summary>
  7. public class ExpressionMapper
  8. {
  9. /// <summary>
  10. /// 字典缓存--hash分布
  11. /// </summary>
  12. private static Dictionary<string, object> _Dic = new Dictionary<string, object>();
  13. /// <summary>
  14. /// 字典缓存表达式树
  15. /// </summary>
  16. /// <typeparam name="TIn"></typeparam>
  17. /// <typeparam name="TOut"></typeparam>
  18. /// <param name="tIn"></param>
  19. /// <returns></returns>
  20. public static TOut Trans<TIn, TOut>(TIn tIn)
  21. {
  22. string key = string.Format("funckey_{0}_{1}", typeof(TIn).FullName, typeof(TOut).FullName);
  23. if (!_Dic.ContainsKey(key))
  24. {
  25. ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
  26. List<MemberBinding> memberBindingList = new List<MemberBinding>();
  27. foreach (var item in typeof(TOut).GetProperties())
  28. {
  29. MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
  30. //Bind 赋值
  31. MemberBinding memberBinding = Expression.Bind(item, property);
  32. memberBindingList.Add(memberBinding);
  33. }
  34. foreach (var item in typeof(TOut).GetFields())
  35. {
  36. MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
  37. MemberBinding memberBinding = Expression.Bind(item, property);
  38. memberBindingList.Add(memberBinding);
  39. }
  40. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
  41. Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
  42. {
  43. parameterExpression
  44. });
  45. Func<TIn, TOut> func = lambda.Compile();//拼装是一次性的
  46. _Dic[key] = func;
  47. }
  48. return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn);
  49. }
  50. }
  51. ///方式5: 生成表达式目录树 泛型缓存 (推荐性能最高,仅次于硬编码)
  52. PeopleCopy peopleCopy6 = ExpressionGenericMapper<People, PeopleCopy>.Trans(people);
  53. /// <summary>
  54. /// 生成表达式目录树 泛型缓存
  55. /// </summary>
  56. /// <typeparam name="TIn"></typeparam>
  57. /// <typeparam name="TOut"></typeparam>
  58. public class ExpressionGenericMapper<TIn, TOut>//Mapper`2
  59. {
  60. private static Func<TIn, TOut> _FUNC = null;
  61. static ExpressionGenericMapper()
  62. {
  63. ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
  64. List<MemberBinding> memberBindingList = new List<MemberBinding>();
  65. foreach (var item in typeof(TOut).GetProperties())
  66. {
  67. MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
  68. MemberBinding memberBinding = Expression.Bind(item, property);
  69. memberBindingList.Add(memberBinding);
  70. }
  71. foreach (var item in typeof(TOut).GetFields())
  72. {
  73. MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
  74. MemberBinding memberBinding = Expression.Bind(item, property);
  75. memberBindingList.Add(memberBinding);
  76. }
  77. MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
  78. Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
  79. {
  80. parameterExpression
  81. });
  82. _FUNC = lambda.Compile();//拼装是一次性的
  83. }
  84. public static TOut Trans(TIn t)
  85. {
  86. return _FUNC(t);
  87. }
  88. }