ReflectionExtensions.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* Copyright 2015-present MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Linq;
  18. using System.Reflection;
  19. using MongoDB.Bson;
  20. namespace MongoDB.Driver.Support
  21. {
  22. internal static class ReflectionExtensions
  23. {
  24. public static object GetDefaultValue(this Type type)
  25. {
  26. if (type.GetTypeInfo().IsValueType)
  27. {
  28. return Activator.CreateInstance(type);
  29. }
  30. return null;
  31. }
  32. public static bool ImplementsInterface(this Type type, Type iface)
  33. {
  34. if (type.Equals(iface))
  35. {
  36. return true;
  37. }
  38. var typeInfo = type.GetTypeInfo();
  39. if (typeInfo.IsGenericType && type.GetGenericTypeDefinition().Equals(iface))
  40. {
  41. return true;
  42. }
  43. return typeInfo.GetInterfaces().Any(i => i.ImplementsInterface(iface));
  44. }
  45. public static bool IsNullable(this Type type)
  46. {
  47. return type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
  48. }
  49. public static bool IsNullableEnum(this Type type)
  50. {
  51. if (!IsNullable(type))
  52. {
  53. return false;
  54. }
  55. return GetNullableUnderlyingType(type).GetTypeInfo().IsEnum;
  56. }
  57. public static bool IsNumeric(this Type type)
  58. {
  59. return
  60. type == typeof(int) ||
  61. type == typeof(long) ||
  62. type == typeof(double) ||
  63. type == typeof(decimal) ||
  64. type == typeof(Decimal128);
  65. }
  66. public static bool IsConvertibleToEnum(this Type type)
  67. {
  68. return
  69. type == typeof(sbyte) ||
  70. type == typeof(short) ||
  71. type == typeof(int) ||
  72. type == typeof(long) ||
  73. type == typeof(byte) ||
  74. type == typeof(ushort) ||
  75. type == typeof(uint) ||
  76. type == typeof(ulong) ||
  77. type == typeof(Enum) ||
  78. type == typeof(string);
  79. }
  80. public static Type GetNullableUnderlyingType(this Type type)
  81. {
  82. if (!IsNullable(type))
  83. {
  84. throw new ArgumentException("Type must be nullable.", "type");
  85. }
  86. return type.GetTypeInfo().GetGenericArguments()[0];
  87. }
  88. public static Type GetSequenceElementType(this Type type)
  89. {
  90. Type ienum = FindIEnumerable(type);
  91. if (ienum == null) { return type; }
  92. return ienum.GetTypeInfo().GetGenericArguments()[0];
  93. }
  94. public static Type FindIEnumerable(this Type seqType)
  95. {
  96. if (seqType == null || seqType == typeof(string))
  97. {
  98. return null;
  99. }
  100. var seqTypeInfo = seqType.GetTypeInfo();
  101. if (seqTypeInfo.IsGenericType && seqTypeInfo.GetGenericTypeDefinition() == typeof(IEnumerable<>))
  102. {
  103. return seqType;
  104. }
  105. if (seqTypeInfo.IsArray)
  106. {
  107. return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
  108. }
  109. if (seqTypeInfo.IsGenericType)
  110. {
  111. foreach (Type arg in seqType.GetTypeInfo().GetGenericArguments())
  112. {
  113. Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
  114. if (ienum.GetTypeInfo().IsAssignableFrom(seqType))
  115. {
  116. return ienum;
  117. }
  118. }
  119. }
  120. Type[] ifaces = seqTypeInfo.GetInterfaces();
  121. if (ifaces != null && ifaces.Length > 0)
  122. {
  123. foreach (Type iface in ifaces)
  124. {
  125. Type ienum = FindIEnumerable(iface);
  126. if (ienum != null) { return ienum; }
  127. }
  128. }
  129. if (seqTypeInfo.BaseType != null && seqTypeInfo.BaseType != typeof(object))
  130. {
  131. return FindIEnumerable(seqTypeInfo.BaseType);
  132. }
  133. return null;
  134. }
  135. }
  136. }