ExpressionUtil.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Reflection;
  5. namespace System.Linq.Expressions
  6. {
  7. static class ExpressionUtil
  8. {
  9. private static TypeCode GetTypeCode(Type type)
  10. {
  11. if (Expression.IsNullableType(type))
  12. type = Expression.GetNonNullableType(type);
  13. return Type.GetTypeCode(type);
  14. }
  15. private static bool IsNumber(TypeCode typeCode)
  16. {
  17. if (IsInteger(typeCode) ||
  18. typeCode == TypeCode.Single ||
  19. typeCode == TypeCode.Double ||
  20. typeCode == TypeCode.Decimal)
  21. return true;
  22. return false;
  23. }
  24. private static bool IsInteger(TypeCode typeCode)
  25. {
  26. if (typeCode == TypeCode.Byte ||
  27. typeCode == TypeCode.SByte ||
  28. typeCode == TypeCode.Int16 ||
  29. typeCode == TypeCode.UInt16 ||
  30. typeCode == TypeCode.Int32 ||
  31. typeCode == TypeCode.UInt32 ||
  32. typeCode == TypeCode.Int64 ||
  33. typeCode == TypeCode.UInt64)
  34. return true;
  35. return false;
  36. }
  37. public static bool IsNumber(Type type)
  38. {
  39. // fast exit: enum is not numeric
  40. if (type.IsEnum)
  41. return false;
  42. return IsNumber(GetTypeCode(type));
  43. }
  44. public static bool IsInteger(Type type)
  45. {
  46. // fast exit: enum is not numeric
  47. if (type.IsEnum)
  48. return false;
  49. return IsInteger(GetTypeCode(type));
  50. }
  51. public static bool IsNumber(object value)
  52. {
  53. if (value == null)
  54. return false;
  55. return IsNumber(value.GetType());
  56. }
  57. public static bool IsInteger(object value)
  58. {
  59. if (value == null)
  60. return false;
  61. return IsInteger(value.GetType());
  62. }
  63. /// <summary>
  64. /// tries to find the method with the given name in one of the
  65. /// given types in the array.
  66. /// </summary>
  67. /// <param name="methodName">The name of the method to find.</param>
  68. /// <param name="types">An array of <see cref="Type"/> (typically 2) defining
  69. /// the types we're going to check for the method.</param>
  70. /// <returns></returns>
  71. public static MethodInfo GetMethod(string methodName, Type[] types)
  72. {
  73. if (types.Length > 2)
  74. throw new ArgumentException();
  75. BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
  76. // the method should have the two types defined as argument...
  77. MethodInfo method = types[0].GetMethod(methodName, flags, null, types, null);
  78. if (method == null && types.Length > 1)
  79. method = types[1].GetMethod(methodName, flags, null, types, null);
  80. return method;
  81. }
  82. public static MethodInfo GetOperatorMethod(string methodName, Type left, Type right)
  83. {
  84. MethodInfo opMethod = GetMethod(methodName, new Type[] { left, right });
  85. if (opMethod == null)
  86. {
  87. if (Expression.IsNullableType(left) &&
  88. Expression.IsNullableType(right))
  89. {
  90. // they're nullable types: try to refine them and get the method again...
  91. left = Expression.GetNonNullableType(left);
  92. right = Expression.GetNonNullableType(right);
  93. opMethod = GetMethod(methodName, new Type[] { left, right });
  94. }
  95. // hope at this point we've found it...
  96. return opMethod;
  97. }
  98. if (!opMethod.IsStatic)
  99. throw new ArgumentException();
  100. if (opMethod.ReturnType == typeof(void))
  101. throw new ArgumentException();
  102. ParameterInfo[] pars = opMethod.GetParameters();
  103. if (pars.Length != 2)
  104. throw new ArgumentException();
  105. ParameterInfo p1 = pars[0];
  106. ParameterInfo p2 = pars[1];
  107. if (p1.ParameterType.IsAssignableFrom(left))
  108. throw new ArgumentException();
  109. if (p2.ParameterType.IsAssignableFrom (right))
  110. throw new ArgumentException();
  111. // check for the nullability of the types...
  112. if (Expression.IsNullableType(p1.ParameterType) &&
  113. !Expression.IsNullableType(left))
  114. throw new InvalidOperationException();
  115. if (Expression.IsNullableType(p2.ParameterType) &&
  116. !Expression.IsNullableType(right))
  117. throw new InvalidOperationException();
  118. return opMethod;
  119. }
  120. public static Type GetNullable(Type type)
  121. {
  122. if (Expression.IsNullableType(type))
  123. return type;
  124. return typeof(Nullable<>).MakeGenericType(type);
  125. }
  126. }
  127. }