ExpressionHelper.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace EasyDevCore.Common
  9. {
  10. /// <summary>
  11. ///
  12. /// </summary>
  13. public static class ExpressionHelper
  14. {
  15. /// <summary>
  16. /// Gets the property.
  17. /// </summary>
  18. /// <typeparam name="TEntity">The type of the entity.</typeparam>
  19. /// <typeparam name="TProperty">The type of the property.</typeparam>
  20. /// <param name="expression">The expression.</param>
  21. /// <returns></returns>
  22. /// <exception cref="InvalidOperationException"></exception>
  23. public static PropertyInfo GetProperty<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> expression)
  24. {
  25. var member = GetMemberExpression(expression).Member;
  26. var property = member as PropertyInfo;
  27. if (property == null)
  28. {
  29. throw new InvalidOperationException(string.Format("Member with Name '{0}' is not a property.", member.Name));
  30. }
  31. return property;
  32. }
  33. /// <summary>
  34. /// Gets the member expression.
  35. /// </summary>
  36. /// <typeparam name="TEntity">The type of the entity.</typeparam>
  37. /// <typeparam name="TProperty">The type of the property.</typeparam>
  38. /// <param name="expression">The expression.</param>
  39. /// <returns></returns>
  40. /// <exception cref="ArgumentException">Not a member access - expression</exception>
  41. private static MemberExpression GetMemberExpression<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> expression)
  42. {
  43. MemberExpression memberExpression = null;
  44. if (expression.Body.NodeType == ExpressionType.Convert)
  45. {
  46. var body = (UnaryExpression)expression.Body;
  47. memberExpression = body.Operand as MemberExpression;
  48. }
  49. else if (expression.Body.NodeType == ExpressionType.MemberAccess)
  50. {
  51. memberExpression = expression.Body as MemberExpression;
  52. }
  53. if (memberExpression == null)
  54. {
  55. throw new ArgumentException("Not a member access", "expression");
  56. }
  57. return memberExpression;
  58. }
  59. /// <summary>
  60. /// Creates the setter.
  61. /// </summary>
  62. /// <typeparam name="TEntity">The type of the entity.</typeparam>
  63. /// <typeparam name="TProperty">The type of the property.</typeparam>
  64. /// <param name="property">The property.</param>
  65. /// <returns></returns>
  66. public static Action<TEntity, TProperty> CreateSetter<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
  67. {
  68. PropertyInfo propertyInfo = ExpressionHelper.GetProperty(property);
  69. ParameterExpression instance = Expression.Parameter(typeof(TEntity), "instance");
  70. ParameterExpression parameter = Expression.Parameter(typeof(TProperty), "param");
  71. var body = Expression.Call(instance, propertyInfo.GetSetMethod(), parameter);
  72. var parameters = new ParameterExpression[] { instance, parameter };
  73. return Expression.Lambda<Action<TEntity, TProperty>>(body, parameters).Compile();
  74. }
  75. /// <summary>
  76. /// Creates the getter.
  77. /// </summary>
  78. /// <typeparam name="TEntity">The type of the entity.</typeparam>
  79. /// <typeparam name="TProperty">The type of the property.</typeparam>
  80. /// <param name="property">The property.</param>
  81. /// <returns></returns>
  82. public static Func<TEntity, TProperty> CreateGetter<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
  83. {
  84. PropertyInfo propertyInfo = ExpressionHelper.GetProperty(property);
  85. ParameterExpression instance = Expression.Parameter(typeof(TEntity), "instance");
  86. var body = Expression.Call(instance, propertyInfo.GetGetMethod());
  87. var parameters = new ParameterExpression[] { instance };
  88. return Expression.Lambda<Func<TEntity, TProperty>>(body, parameters).Compile();
  89. }
  90. /// <summary>
  91. /// Creates the default constructor.
  92. /// </summary>
  93. /// <typeparam name="TEntity">The type of the entity.</typeparam>
  94. /// <returns></returns>
  95. public static Func<TEntity> CreateDefaultConstructor<TEntity>()
  96. {
  97. var body = Expression.New(typeof(TEntity));
  98. var lambda = Expression.Lambda<Func<TEntity>>(body);
  99. return lambda.Compile();
  100. }
  101. /// <summary>
  102. /// Gets the property getter.
  103. /// </summary>
  104. /// <typeparam name="TObject">The type of the object.</typeparam>
  105. /// <typeparam name="TProperty">The type of the property.</typeparam>
  106. /// <param name="propertyName">Name of the property.</param>
  107. /// <returns></returns>
  108. public static Func<TObject, TProperty> GetPropGetter<TObject, TProperty>(string propertyName)
  109. {
  110. ParameterExpression paramExpression = Expression.Parameter(typeof(TObject), "value");
  111. Expression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
  112. Func<TObject, TProperty> result =
  113. Expression.Lambda<Func<TObject, TProperty>>(propertyGetterExpression, paramExpression).Compile();
  114. return result;
  115. }
  116. /// <summary>
  117. /// Gets the property setter.
  118. /// </summary>
  119. /// <typeparam name="TObject">The type of the object.</typeparam>
  120. /// <typeparam name="TProperty">The type of the property.</typeparam>
  121. /// <param name="propertyName">Name of the property.</param>
  122. /// <returns></returns>
  123. public static Action<TObject, TProperty> GetPropSetter<TObject, TProperty>(string propertyName)
  124. {
  125. ParameterExpression paramExpression = Expression.Parameter(typeof(TObject));
  126. ParameterExpression paramExpression2 = Expression.Parameter(typeof(TProperty), propertyName);
  127. MemberExpression propertyGetterExpression = Expression.Property(paramExpression, propertyName);
  128. Action<TObject, TProperty> result = Expression.Lambda<Action<TObject, TProperty>>
  129. (
  130. Expression.Assign(propertyGetterExpression, paramExpression2), paramExpression, paramExpression2
  131. ).Compile();
  132. return result;
  133. }
  134. /// <summary>
  135. /// Gets the value getter.
  136. /// var getter = property.GetValueGetter&lt;ReflectedType&gt;();
  137. /// </summary>
  138. /// <typeparam name="T"></typeparam>
  139. /// <param name="propertyInfo">The property information.</param>
  140. /// <returns></returns>
  141. /// <exception cref="ArgumentException"></exception>
  142. public static Func<T, object> GetValueGetter<T>(this PropertyInfo propertyInfo)
  143. {
  144. if (typeof(T) != propertyInfo.DeclaringType)
  145. {
  146. throw new ArgumentException();
  147. }
  148. var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
  149. var property = Expression.Property(instance, propertyInfo);
  150. var convert = Expression.TypeAs(property, typeof(object));
  151. return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
  152. }
  153. /// <summary>
  154. /// Gets the value setter.
  155. /// var setter = property.GetValueSetter&lt;ReflectedType&gt;();
  156. /// </summary>
  157. /// <typeparam name="T"></typeparam>
  158. /// <param name="propertyInfo">The property information.</param>
  159. /// <returns></returns>
  160. /// <exception cref="ArgumentException"></exception>
  161. public static Action<T, object> GetValueSetter<T>(this PropertyInfo propertyInfo)
  162. {
  163. if (typeof(T) != propertyInfo.DeclaringType)
  164. {
  165. throw new ArgumentException();
  166. }
  167. var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
  168. var argument = Expression.Parameter(typeof(object), "a");
  169. var setterCall = Expression.Call(
  170. instance,
  171. propertyInfo.GetSetMethod(),
  172. Expression.Convert(argument, propertyInfo.PropertyType));
  173. return (Action<T, object>)Expression.Lambda(setterCall, instance, argument).Compile();
  174. }
  175. }
  176. }