You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LuExpressionUtils.cs 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using Luticate2.Auth.Utils.Dbo;
  7. using Luticate2.Auth.Utils.Dbo.Result;
  8. namespace Luticate2.Auth.Utils.Business
  9. {
  10. public static class LuExpressionUtils
  11. {
  12. public static Expression GetFromConvert(Expression exp)
  13. {
  14. Expression e = exp;
  15. if (exp is LambdaExpression lambdaExpression)
  16. {
  17. e = lambdaExpression.Body;
  18. }
  19. Expression operand;
  20. if ((e.NodeType == ExpressionType.Convert ||
  21. e.NodeType == ExpressionType.ConvertChecked)
  22. && e is UnaryExpression)
  23. {
  24. operand = ((UnaryExpression) e).Operand;
  25. }
  26. else
  27. {
  28. operand = e;
  29. }
  30. return operand;
  31. }
  32. public static Expression<Func<TType1, TType3>> AddConvert<TType1, TType2, TType3>(Expression<Func<TType1, TType2>> exp)
  33. {
  34. var converted = Expression.Convert(exp, typeof(object));
  35. var expLambda = Expression.Lambda<Func<TType1, TType3>>(converted, exp.Parameters);
  36. return expLambda;
  37. }
  38. public static LuResult<TProperty> SetValueFromExpression<TDbo, TProperty>(Expression<Func<TDbo, TProperty>> property,
  39. TDbo dboTo, TProperty value)
  40. {
  41. var memberInfo = GetSingleMemberFromExpression(property);
  42. if (memberInfo != null)
  43. {
  44. switch (memberInfo.MemberType)
  45. {
  46. case MemberTypes.Field:
  47. ((FieldInfo) memberInfo).SetValue(dboTo, value);
  48. return LuResult<TProperty>.Ok(value);
  49. case MemberTypes.Property:
  50. ((PropertyInfo) memberInfo).SetValue(dboTo, value);
  51. return LuResult<TProperty>.Ok(value);
  52. default:
  53. return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(),
  54. $"Bad MemberType: {memberInfo.MemberType}");
  55. }
  56. }
  57. return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(), "Bad member expression");
  58. }
  59. public static LuResult<TProperty> GetValueFromExpression<TDbo, TProperty>(Expression<Func<TDbo, TProperty>> property,
  60. TDbo dboTo)
  61. {
  62. var memberInfo = GetSingleMemberFromExpression(property);
  63. if (memberInfo != null)
  64. {
  65. TProperty value;
  66. switch (memberInfo.MemberType)
  67. {
  68. case MemberTypes.Field:
  69. value = (TProperty) ((FieldInfo) memberInfo).GetValue(dboTo);
  70. return LuResult<TProperty>.Ok(value);
  71. case MemberTypes.Property:
  72. value = (TProperty) ((PropertyInfo) memberInfo).GetValue(dboTo);
  73. return LuResult<TProperty>.Ok(value);
  74. default:
  75. return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(),
  76. $"Bad MemberType: {memberInfo.MemberType}");
  77. }
  78. }
  79. return LuResult<TProperty>.Error(LuStatus.InternalError.ToInt(), "Bad member expression");
  80. }
  81. public static MemberInfo GetSingleMemberFromExpression(LambdaExpression property)
  82. {
  83. if (GetFromConvert(property) is MemberExpression memberExpression &&
  84. (memberExpression.Expression == property.Parameters.First() ||
  85. (memberExpression.Expression == null && memberExpression.Member.DeclaringType == property.Parameters.First().Type)))
  86. {
  87. return memberExpression.Member;
  88. }
  89. return null;
  90. }
  91. public static MethodInfo GetSingleMethodFromExpression(LambdaExpression method)
  92. {
  93. // TODO check if something like methodCallExpression.Method.DeclaringType == method.Parameters.First().Type is usefull/required (static/extension methods)
  94. if (GetFromConvert(method) is MethodCallExpression methodCallExpression &&
  95. (methodCallExpression.Object == method.Parameters.First() || methodCallExpression.Object == null))
  96. {
  97. return methodCallExpression.Method;
  98. }
  99. return null;
  100. }
  101. private static bool GetMembersFromExpression<TTypeTo, TProperty>(
  102. Expression<Func<TTypeTo, TProperty>> property, IList<MemberInfo> memberInfos)
  103. {
  104. MemberExpression memberExpression;
  105. if ((property.Body.NodeType == ExpressionType.Convert ||
  106. property.Body.NodeType == ExpressionType.ConvertChecked)
  107. && property.Body is UnaryExpression)
  108. {
  109. memberExpression = ((UnaryExpression) property.Body).Operand as MemberExpression;
  110. }
  111. else
  112. {
  113. memberExpression = property.Body as MemberExpression;
  114. }
  115. if (memberExpression != null)
  116. {
  117. if (memberExpression.Expression == property.Parameters.First())
  118. {
  119. memberInfos.Add(memberExpression.Member);
  120. return true;
  121. }
  122. else if (memberExpression.Expression is MemberExpression)
  123. {
  124. var exp = Expression.Lambda<Func<TTypeTo, object>>(memberExpression.Expression, property.Parameters);
  125. var res = GetMembersFromExpression(exp, memberInfos);
  126. if (res)
  127. {
  128. memberInfos.Add(memberExpression.Member);
  129. }
  130. return res;
  131. }
  132. }
  133. return false;
  134. }
  135. public static IList<MemberInfo> GetMembersFromExpression<TTypeTo, TProperty>(Expression<Func<TTypeTo, TProperty>> property)
  136. {
  137. var list = new List<MemberInfo>();
  138. if (GetMembersFromExpression(property, list))
  139. {
  140. return list;
  141. }
  142. return null;
  143. }
  144. }
  145. }