1616using System ;
1717using System . Collections . Generic ;
1818using System . Linq ;
19+ using System . Reflection ;
1920using System . Runtime . CompilerServices ;
21+ using MongoDB . Bson ;
2022
2123namespace MongoDB . Driver . Linq . Linq3Implementation . Misc
2224{
2325 internal static class TypeExtensions
2426 {
25- private static readonly Type [ ] __dictionaryInterfaces =
27+ private static readonly Type [ ] __dictionaryInterfaceDefinitions =
2628 {
2729 typeof ( IDictionary < , > ) ,
2830 typeof ( IReadOnlyDictionary < , > )
@@ -52,6 +54,14 @@ internal static class TypeExtensions
5254 typeof ( ValueTuple < , , , , , , , > )
5355 } ;
5456
57+ public static object GetDefaultValue ( this Type type )
58+ {
59+ var genericMethod = typeof ( TypeExtensions )
60+ . GetMethod ( nameof ( GetDefaultValueGeneric ) , BindingFlags . NonPublic | BindingFlags . Static )
61+ . MakeGenericMethod ( type ) ;
62+ return genericMethod . Invoke ( null , null ) ;
63+ }
64+
5565 public static Type GetIEnumerableGenericInterface ( this Type enumerableType )
5666 {
5767 if ( enumerableType . TryGetIEnumerableGenericInterface ( out var ienumerableGenericInterface ) )
@@ -92,7 +102,7 @@ public static bool Implements(this Type type, Type @interface)
92102
93103 public static bool ImplementsDictionaryInterface ( this Type type , out Type keyType , out Type valueType )
94104 {
95- if ( TryGetGenericInterface ( type , __dictionaryInterfaces , out var dictionaryInterface ) )
105+ if ( TryGetGenericInterface ( type , __dictionaryInterfaceDefinitions , out var dictionaryInterface ) )
96106 {
97107 var genericArguments = dictionaryInterface . GetGenericArguments ( ) ;
98108 keyType = genericArguments [ 0 ] ;
@@ -136,6 +146,18 @@ public static bool ImplementsIList(this Type type, out Type itemType)
136146 return false ;
137147 }
138148
149+ public static bool ImplementsIQueryable ( this Type type , out Type itemType )
150+ {
151+ if ( TryGetIQueryableGenericInterface ( type , out var iqueryableType ) )
152+ {
153+ itemType = iqueryableType . GetGenericArguments ( ) [ 0 ] ;
154+ return true ;
155+ }
156+
157+ itemType = null ;
158+ return false ;
159+ }
160+
139161 public static bool Is ( this Type type , Type comparand )
140162 {
141163 if ( type == comparand )
@@ -175,41 +197,49 @@ public static bool IsArray(this Type type, out Type itemType)
175197 return false ;
176198 }
177199
200+ public static bool IsBooleanOrNullableBoolean ( this Type type )
201+ {
202+ return
203+ type == typeof ( bool ) ||
204+ type . IsNullable ( out var valueType ) && valueType == typeof ( bool ) ;
205+ }
206+
207+ public static bool IsConvertibleToEnum ( this Type type )
208+ {
209+ return
210+ type == typeof ( sbyte ) ||
211+ type == typeof ( short ) ||
212+ type == typeof ( int ) ||
213+ type == typeof ( long ) ||
214+ type == typeof ( byte ) ||
215+ type == typeof ( ushort ) ||
216+ type == typeof ( uint ) ||
217+ type == typeof ( ulong ) ||
218+ type == typeof ( Enum ) ||
219+ type == typeof ( string ) ;
220+ }
221+
178222 public static bool IsEnum ( this Type type , out Type underlyingType )
179223 {
180224 if ( type . IsEnum )
181225 {
182226 underlyingType = Enum . GetUnderlyingType ( type ) ;
183227 return true ;
184228 }
185- else
186- {
187- underlyingType = null ;
188- return false ;
189- }
229+
230+ underlyingType = null ;
231+ return false ;
190232 }
191233
192- public static bool IsEnum ( this Type type , out Type enumType , out Type underlyingType )
234+ public static bool IsEnumOrNullableEnum ( this Type type , out Type enumType , out Type underlyingType )
193235 {
194- if ( type . IsEnum )
236+ if ( type . IsEnum ( out underlyingType ) )
195237 {
196238 enumType = type ;
197- underlyingType = Enum . GetUnderlyingType ( type ) ;
198239 return true ;
199240 }
200- else
201- {
202- enumType = null ;
203- underlyingType = null ;
204- return false ;
205- }
206- }
207241
208- public static bool IsEnumOrNullableEnum ( this Type type , out Type enumType , out Type underlyingType )
209- {
210- return
211- type . IsEnum ( out enumType , out underlyingType ) ||
212- type . IsNullableEnum ( out enumType , out underlyingType ) ;
242+ return IsNullableEnum ( type , out enumType , out underlyingType ) ;
213243 }
214244
215245 public static bool IsNullable ( this Type type )
@@ -224,23 +254,39 @@ public static bool IsNullable(this Type type, out Type valueType)
224254 valueType = type . GetGenericArguments ( ) [ 0 ] ;
225255 return true ;
226256 }
227- else
228- {
229- valueType = null ;
230- return false ;
231- }
257+
258+ valueType = null ;
259+ return false ;
232260 }
233261
234262 public static bool IsNullableEnum ( this Type type )
235263 {
236264 return type . IsNullable ( out var valueType ) && valueType . IsEnum ;
237265 }
238266
267+ public static bool IsNullableEnum ( this Type type , out Type enumType )
268+ {
269+ if ( type . IsNullable ( out var valueType ) && valueType . IsEnum )
270+ {
271+ enumType = valueType ;
272+ return true ;
273+ }
274+
275+ enumType = null ;
276+ return false ;
277+ }
278+
239279 public static bool IsNullableEnum ( this Type type , out Type enumType , out Type underlyingType )
240280 {
281+ if ( type . IsNullable ( out var valueType ) && valueType . IsEnum ( out underlyingType ) )
282+ {
283+ enumType = valueType ;
284+ return true ;
285+ }
286+
241287 enumType = null ;
242288 underlyingType = null ;
243- return type . IsNullable ( out var valueType ) && valueType . IsEnum ( out enumType , out underlyingType ) ;
289+ return false ;
244290 }
245291
246292 public static bool IsNullableOf ( this Type type , Type valueType )
@@ -256,6 +302,24 @@ public static bool IsReadOnlySpanOf(this Type type, Type itemType)
256302 type . GetGenericArguments ( ) [ 0 ] == itemType ;
257303 }
258304
305+ public static bool IsNumeric ( this Type type )
306+ {
307+ return
308+ type == typeof ( int ) ||
309+ type == typeof ( long ) ||
310+ type == typeof ( double ) ||
311+ type == typeof ( float ) ||
312+ type == typeof ( decimal ) ||
313+ type == typeof ( Decimal128 ) ;
314+ }
315+
316+ public static bool IsNumericOrNullableNumeric ( this Type type )
317+ {
318+ return
319+ type . IsNumeric ( ) ||
320+ type . IsNullable ( out var valueType ) && valueType . IsNumeric ( ) ;
321+ }
322+
259323 public static bool IsSameAsOrNullableOf ( this Type type , Type valueType )
260324 {
261325 return type == valueType || type . IsNullableOf ( valueType ) ;
@@ -298,55 +362,36 @@ public static bool IsValueTuple(this Type type)
298362 __valueTupleTypeDefinitions . Contains ( typeDefinition ) ;
299363 }
300364
301- public static bool TryGetGenericInterface ( this Type type , Type [ ] interfaceDefinitions , out Type genericInterface )
365+ public static bool TryGetGenericInterface ( this Type type , Type genericInterfaceDefintion , out Type genericInterface )
302366 {
303367 genericInterface =
304- type . IsConstructedGenericType && interfaceDefinitions . Contains ( type . GetGenericTypeDefinition ( ) ) ?
368+ type . IsConstructedGenericType && type . GetGenericTypeDefinition ( ) == genericInterfaceDefintion ?
305369 type :
306- type . GetInterfaces ( ) . FirstOrDefault ( i => i . IsConstructedGenericType && interfaceDefinitions . Contains ( i . GetGenericTypeDefinition ( ) ) ) ;
370+ type . GetInterfaces ( ) . FirstOrDefault ( i => i . IsConstructedGenericType && i . GetGenericTypeDefinition ( ) == genericInterfaceDefintion ) ;
307371 return genericInterface != null ;
308372 }
309373
310- public static bool TryGetIEnumerableGenericInterface ( this Type type , out Type ienumerableGenericInterface )
374+ public static bool TryGetGenericInterface ( this Type type , Type [ ] genericInterfaceDefinitions , out Type genericInterface )
311375 {
312- if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( IEnumerable < > ) )
313- {
314- ienumerableGenericInterface = type ;
315- return true ;
316- }
317-
318- foreach ( var interfaceType in type . GetInterfaces ( ) )
319- {
320- if ( interfaceType . IsGenericType && interfaceType . GetGenericTypeDefinition ( ) == typeof ( IEnumerable < > ) )
321- {
322- ienumerableGenericInterface = interfaceType ;
323- return true ;
324- }
325- }
326-
327- ienumerableGenericInterface = null ;
328- return false ;
376+ genericInterface =
377+ type . IsConstructedGenericType && genericInterfaceDefinitions . Contains ( type . GetGenericTypeDefinition ( ) ) ?
378+ type :
379+ type . GetInterfaces ( ) . FirstOrDefault ( i => i . IsConstructedGenericType && genericInterfaceDefinitions . Contains ( i . GetGenericTypeDefinition ( ) ) ) ;
380+ return genericInterface != null ;
329381 }
330382
383+ public static bool TryGetIEnumerableGenericInterface ( this Type type , out Type ienumerableGenericInterface )
384+ => TryGetGenericInterface ( type , typeof ( IEnumerable < > ) , out ienumerableGenericInterface ) ;
385+
331386 public static bool TryGetIListGenericInterface ( this Type type , out Type ilistGenericInterface )
332- {
333- if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( IList < > ) )
334- {
335- ilistGenericInterface = type ;
336- return true ;
337- }
387+ => TryGetGenericInterface ( type , typeof ( IList < > ) , out ilistGenericInterface ) ;
338388
339- foreach ( var interfaceType in type . GetInterfaces ( ) )
340- {
341- if ( interfaceType . IsGenericType && interfaceType . GetGenericTypeDefinition ( ) == typeof ( IList < > ) )
342- {
343- ilistGenericInterface = interfaceType ;
344- return true ;
345- }
346- }
389+ public static bool TryGetIQueryableGenericInterface ( this Type type , out Type iqueryableGenericInterface )
390+ => TryGetGenericInterface ( type , typeof ( IQueryable < > ) , out iqueryableGenericInterface ) ;
347391
348- ilistGenericInterface = null ;
349- return false ;
392+ private static TValue GetDefaultValueGeneric < TValue > ( )
393+ {
394+ return default ( TValue ) ;
350395 }
351396 }
352397}
0 commit comments