2
0

ReflectionExtensions.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System.Reflection;
  2. using System.Runtime.CompilerServices;
  3. using Jint.Native;
  4. using Jint.Runtime;
  5. namespace Jint.Extensions
  6. {
  7. internal static class ReflectionExtensions
  8. {
  9. private static readonly Type nullableType = typeof(Nullable<>);
  10. internal static void SetValue(this MemberInfo memberInfo, object forObject, object value)
  11. {
  12. if (memberInfo.MemberType == MemberTypes.Field)
  13. {
  14. var fieldInfo = (FieldInfo) memberInfo;
  15. if (value != null && fieldInfo.FieldType.IsInstanceOfType(value))
  16. {
  17. fieldInfo.SetValue(forObject, value);
  18. }
  19. }
  20. else if (memberInfo.MemberType == MemberTypes.Property)
  21. {
  22. var propertyInfo = (PropertyInfo) memberInfo;
  23. if (value != null && propertyInfo.PropertyType.IsInstanceOfType(value))
  24. {
  25. propertyInfo.SetValue(forObject, value);
  26. }
  27. }
  28. }
  29. internal static Type GetDefinedType(this MemberInfo memberInfo)
  30. {
  31. return memberInfo switch
  32. {
  33. PropertyInfo propertyInfo => propertyInfo.PropertyType,
  34. FieldInfo fieldInfo => fieldInfo.FieldType,
  35. _ => null
  36. };
  37. }
  38. internal static IEnumerable<MethodInfo> GetExtensionMethods(this Type type)
  39. {
  40. return type.GetMethods(BindingFlags.Public | BindingFlags.Static)
  41. .Where(m => m.IsExtensionMethod());
  42. }
  43. internal static IEnumerable<MethodInfo> GetOperatorOverloadMethods(this Type type)
  44. {
  45. return type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
  46. .Where(m => m.IsSpecialName);
  47. }
  48. private static bool IsExtensionMethod(this MethodBase methodInfo)
  49. {
  50. return methodInfo.IsDefined(typeof(ExtensionAttribute), true);
  51. }
  52. public static bool IsNullable(this Type type)
  53. {
  54. return type is { IsGenericType: true } && type.GetGenericTypeDefinition() == nullableType;
  55. }
  56. public static bool IsNumeric(this Type type)
  57. {
  58. if (type == null || type.IsEnum)
  59. {
  60. return false;
  61. }
  62. switch (Type.GetTypeCode(type))
  63. {
  64. case TypeCode.Byte:
  65. case TypeCode.Decimal:
  66. case TypeCode.Double:
  67. case TypeCode.Int16:
  68. case TypeCode.Int32:
  69. case TypeCode.Int64:
  70. case TypeCode.SByte:
  71. case TypeCode.Single:
  72. case TypeCode.UInt16:
  73. case TypeCode.UInt32:
  74. case TypeCode.UInt64:
  75. return true;
  76. default:
  77. return false;
  78. }
  79. }
  80. public static bool IsClrNumericCoercible(this Type type)
  81. {
  82. if (type == null || type.IsEnum)
  83. {
  84. return false;
  85. }
  86. switch (Type.GetTypeCode(type))
  87. {
  88. case TypeCode.Decimal:
  89. case TypeCode.Double:
  90. case TypeCode.Int32:
  91. case TypeCode.Int64:
  92. return true;
  93. default:
  94. return false;
  95. }
  96. }
  97. public static object AsNumberOfType(this double d, TypeCode type)
  98. {
  99. switch (type)
  100. {
  101. case TypeCode.Decimal:
  102. return (decimal) d;
  103. case TypeCode.Double:
  104. return d;
  105. case TypeCode.Int32:
  106. return (int) d;
  107. case TypeCode.Int64:
  108. return (long) d;
  109. default:
  110. ExceptionHelper.ThrowArgumentException("Cannot convert " + type);
  111. return null;
  112. }
  113. }
  114. public static bool TryConvertViaTypeCoercion(
  115. Type _memberType,
  116. ValueCoercionType valueCoercionType,
  117. JsValue value,
  118. out object converted)
  119. {
  120. if (_memberType == typeof(bool) && (valueCoercionType & ValueCoercionType.Boolean) != 0)
  121. {
  122. converted = TypeConverter.ToBoolean(value);
  123. return true;
  124. }
  125. if (_memberType == typeof(string)
  126. && !value.IsNullOrUndefined()
  127. && (valueCoercionType & ValueCoercionType.String) != 0)
  128. {
  129. // we know how to print out correct string presentation for primitives
  130. // that are non-null and non-undefined
  131. converted = TypeConverter.ToString(value);
  132. return true;
  133. }
  134. if (_memberType.IsClrNumericCoercible() && (valueCoercionType & ValueCoercionType.Number) != 0)
  135. {
  136. // we know how to print out correct string presentation for primitives
  137. // that are non-null and non-undefined
  138. var number = TypeConverter.ToNumber(value);
  139. converted = number.AsNumberOfType(Type.GetTypeCode(_memberType));
  140. return true;
  141. }
  142. converted = null;
  143. return false;
  144. }
  145. }
  146. }