comparison Source/Reflection/TypeHelper.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.Diagnostics.CodeAnalysis;
6 using System.IO;
7 using System.Linq;
8 using System.Reflection;
9 using System.Xml;
10
11 #if !SILVERLIGHT
12 using System.Xml.Linq;
13 #endif
14
15 namespace BLToolkit.Reflection
16 {
17 #if !SILVERLIGHT && !DATA
18 using EditableObjects;
19 #endif
20 using DataAccess;
21 using TypeBuilder;
22
23 /// <summary>
24 /// A wrapper around the <see cref="Type"/> class.
25 /// </summary>
26 [System.Diagnostics.DebuggerDisplay("Type = {Type}")]
27 public class TypeHelper
28 {
29 /// <summary>
30 /// Initializes a new instance of the <see cref="TypeHelper"/> class.
31 /// </summary>
32 /// <param name="type">The Type to wrap.</param>
33 public TypeHelper(Type type)
34 {
35 if (type == null) throw new ArgumentNullException("type");
36
37 Type = type;
38 }
39
40 /// <summary>
41 /// Gets associated Type.
42 /// </summary>
43 public Type Type { get; private set; }
44
45 /// <summary>
46 /// Converts the supplied <see cref="Type"/> to a <see cref="TypeHelper"/>.
47 /// </summary>
48 /// <param name="type">The Type.</param>
49 /// <returns>A TypeHelper.</returns>
50 public static implicit operator TypeHelper(Type type)
51 {
52 if (type == null) throw new ArgumentNullException("type");
53
54 return new TypeHelper(type);
55 }
56
57 /// <summary>
58 /// Converts the supplied <see cref="TypeHelper"/> to a <see cref="Type"/>.
59 /// </summary>
60 /// <param name="typeHelper">The TypeHelper.</param>
61 /// <returns>A Type.</returns>
62 public static implicit operator Type(TypeHelper typeHelper)
63 {
64 if (typeHelper == null) throw new ArgumentNullException("typeHelper");
65
66 return typeHelper.Type;
67 }
68
69 #region GetAttributes
70
71 /// <summary>
72 /// Returns an array of custom attributes identified by <b>Type</b>.
73 /// </summary>
74 /// <param name="attributeType">The type of attribute to search for.
75 /// Only attributes that are assignable to this type are returned.</param>
76 /// <param name="inherit">Specifies whether to search this member's inheritance chain
77 /// to find the attributes.</param>
78 /// <returns>An array of custom attributes defined on this reflected member,
79 /// or an array with zero (0) elements if no attributes are defined.</returns>
80 public object[] GetCustomAttributes(Type attributeType, bool inherit)
81 {
82 return Type.GetCustomAttributes(attributeType, inherit);
83 }
84
85 /// <summary>
86 /// Returns an array of custom attributes identified by <b>Type</b>
87 /// including attribute's inheritance chain.
88 /// </summary>
89 /// <param name="attributeType">The type of attribute to search for.
90 /// Only attributes that are assignable to this type are returned.</param>
91 /// <returns>An array of custom attributes defined on this reflected member,
92 /// or an array with zero (0) elements if no attributes are defined.</returns>
93 public object[] GetCustomAttributes(Type attributeType)
94 {
95 return Type.GetCustomAttributes(attributeType, true);
96 }
97
98
99 /// <summary>
100 /// Returns an array of all of the custom attributes.
101 /// </summary>
102 /// <param name="inherit">Specifies whether to search this member's inheritance chain
103 /// to find the attributes.</param>
104 /// <returns>An array of custom attributes defined on this reflected member,
105 /// or an array with zero (0) elements if no attributes are defined.</returns>
106 public object[] GetCustomAttributes(bool inherit)
107 {
108 return Type.GetCustomAttributes(inherit);
109 }
110
111 /// <summary>
112 /// Returns an array of all of the custom attributes including attributes' inheritance chain.
113 /// </summary>
114 /// <returns>An array of custom attributes defined on this reflected member,
115 /// or an array with zero (0) elements if no attributes are defined.</returns>
116 public object[] GetCustomAttributes()
117 {
118 return Type.GetCustomAttributes(true);
119 }
120
121 /// <summary>
122 /// Returns an array of all custom attributes identified by <b>Type</b> including type's
123 /// inheritance chain.
124 /// </summary>
125 /// <param name="attributeType">The type of attribute to search for.
126 /// Only attributes that are assignable to this type are returned.</param>
127 /// <returns>An array of custom attributes defined on this reflected member,
128 /// or an array with zero (0) elements if no attributes are defined.</returns>
129 public object[] GetAttributes(Type attributeType)
130 {
131 return GetAttributes(Type, attributeType);
132 }
133
134 /// <summary>
135 /// Returns an array of all custom attributes including type's inheritance chain.
136 /// </summary>
137 /// <returns>An array of custom attributes defined on this reflected member,
138 /// or an array with zero (0) elements if no attributes are defined.</returns>
139 public object[] GetAttributes()
140 {
141 return GetAttributesInternal();
142 }
143
144 #region Attributes cache
145
146 object[] GetAttributesInternal()
147 {
148 lock (_typeAttributes)
149 {
150 var key = Type.FullName;
151
152 object[] attrs;
153
154 if (!_typeAttributes.TryGetValue(key, out attrs))
155 {
156 var list = new List<object>();
157
158 GetAttributesInternal(list, Type);
159
160 _typeAttributes.Add(key, attrs = list.ToArray());
161 }
162
163 return attrs;
164 }
165 }
166
167 static readonly Dictionary<Type,object[]> _typeAttributesTopInternal = new Dictionary<Type,object[]>(10);
168
169 static void GetAttributesInternal(List<object> list, Type type)
170 {
171 object[] attrs;
172
173 if (_typeAttributesTopInternal.TryGetValue(type, out attrs))
174 list.AddRange(attrs);
175 else
176 {
177 GetAttributesTreeInternal(list, type);
178 _typeAttributesTopInternal.Add(type, list.ToArray());
179 }
180 }
181
182 static readonly Dictionary<Type,object[]> _typeAttributesInternal = new Dictionary<Type,object[]>(10);
183
184 static void GetAttributesTreeInternal(List<object> list, Type type)
185 {
186 object[] attrs;
187
188 if (!_typeAttributesInternal.TryGetValue(type, out attrs))
189 _typeAttributesInternal.Add(type, attrs = type.GetCustomAttributes(false));
190
191 if (Common.Configuration.FilterOutBaseEqualAttributes)
192 {
193 foreach (var t in attrs)
194 if (!list.Contains(t))
195 list.Add(t);
196 }
197 else
198 list.AddRange(attrs);
199
200 if (type.IsInterface)
201 return;
202
203 // Reflection returns interfaces for the whole inheritance chain.
204 // So, we are going to get some hemorrhoid here to restore the inheritance sequence.
205 //
206 var interfaces = type.GetInterfaces();
207 var nBaseInterfaces = type.BaseType != null? type.BaseType.GetInterfaces().Length: 0;
208
209 for (var i = 0; i < interfaces.Length; i++)
210 {
211 var intf = interfaces[i];
212
213 if (i < nBaseInterfaces)
214 {
215 var getAttr = false;
216
217 foreach (var mi in type.GetInterfaceMap(intf).TargetMethods)
218 {
219 // Check if the interface is reimplemented.
220 //
221 if (mi.DeclaringType == type)
222 {
223 getAttr = true;
224 break;
225 }
226 }
227
228 if (getAttr == false)
229 continue;
230 }
231
232 GetAttributesTreeInternal(list, intf);
233 }
234
235 if (type.BaseType != null && type.BaseType != typeof(object))
236 GetAttributesTreeInternal(list, type.BaseType);
237 }
238
239 static readonly Dictionary<string,object[]> _typeAttributes = new Dictionary<string, object[]>(10);
240
241 #endregion
242
243 /// <summary>
244 /// Returns an array of custom attributes applied to a type.
245 /// </summary>
246 /// <param name="type">A type instance.</param>
247 /// <param name="attributeType">The type of attribute to search for.
248 /// Only attributes that are assignable to this type are returned.</param>
249 /// <returns>An array of custom attributes applied to this type,
250 /// or an array with zero (0) elements if no attributes have been applied.</returns>
251 public static object[] GetAttributes(Type type, Type attributeType)
252 {
253 if (type == null) throw new ArgumentNullException("type");
254 if (attributeType == null) throw new ArgumentNullException("attributeType");
255
256 lock (_typeAttributes)
257 {
258 var key = type.FullName + "#" + attributeType.FullName;
259
260 object[] attrs;
261
262 if (!_typeAttributes.TryGetValue(key, out attrs))
263 {
264 var list = new List<object>();
265
266 GetAttributesInternal(list, type);
267
268 for (var i = 0; i < list.Count; i++)
269 if (attributeType.IsInstanceOfType(list[i]) == false)
270 list.RemoveAt(i--);
271
272 _typeAttributes.Add(key, attrs = list.ToArray());
273 }
274
275 return attrs;
276 }
277 }
278
279 /// <summary>
280 /// Retrieves a custom attribute applied to a type.
281 /// </summary>
282 /// <param name="type">A type instance.</param>
283 /// <param name="attributeType">The type of attribute to search for.
284 /// Only attributes that are assignable to this type are returned.</param>
285 /// <returns>A reference to the first custom attribute of type <paramref name="attributeType"/>
286 /// that is applied to element, or null if there is no such attribute.</returns>
287 public static Attribute GetFirstAttribute(Type type, Type attributeType)
288 {
289 var attrs = new TypeHelper(type).GetAttributes(attributeType);
290
291 return attrs.Length > 0? (Attribute)attrs[0]: null;
292 }
293
294 /// <summary>
295 /// Retrieves a custom attribute applied to a type.
296 /// </summary>
297 /// <param name="type">A type instance.</param>
298 /// <typeparam name="T">The type of attribute to search for.
299 /// Only attributes that are assignable to this type are returned.</param>
300 /// <returns>A reference to the first custom attribute of type attributeType
301 /// that is applied to element, or null if there is no such attribute.</returns>
302 public static T GetFirstAttribute<T>(Type type) where T : Attribute
303 {
304 var attrs = new TypeHelper(type).GetAttributes(typeof(T));
305
306 return attrs.Length > 0? (T)attrs[0]: null;
307 }
308
309 #endregion
310
311 #region Property Wrappers
312
313 /// <summary>
314 /// Gets the fully qualified name of the Type, including the namespace of the Type.
315 /// </summary>
316 public string FullName
317 {
318 get { return Type.FullName; }
319 }
320
321 /// <summary>
322 /// Gets the name of the Type.
323 /// </summary>
324 public string Name
325 {
326 get { return Type.Name; }
327 }
328
329 /// <summary>
330 /// Gets a value indicating whether the Type is abstract and must be overridden.
331 /// </summary>
332 public bool IsAbstract
333 {
334 get { return Type.IsAbstract; }
335 }
336
337 /// <summary>
338 /// Gets a value indicating whether the System.Type is an array.
339 /// </summary>
340 public bool IsArray
341 {
342 get { return Type.IsArray; }
343 }
344
345 /// <summary>
346 /// Gets a value indicating whether the Type is a value type.
347 /// </summary>
348 public bool IsValueType
349 {
350 get { return Type.IsValueType; }
351 }
352
353 /// <summary>
354 /// Gets a value indicating whether the Type is a class; that is, not a value type or interface.
355 /// </summary>
356 public bool IsClass
357 {
358 get { return Type.IsClass; }
359 }
360
361 /// <summary>
362 /// Gets a value indicating whether the System.Type is an interface; that is, not a class or a value type.
363 /// </summary>
364 public bool IsInterface
365 {
366 get { return Type.IsInterface; }
367 }
368
369 /// <summary>
370 /// Indicates whether the Type is serializable.
371 /// </summary>
372 public bool IsSerializable
373 {
374 get
375 {
376 #if SILVERLIGHT
377 return false;
378 #else
379 return Type.IsSerializable;
380 #endif
381 }
382 }
383
384 #endregion
385
386 #region GetMethods
387
388 /// <summary>
389 /// Returns all the methods of the current Type.
390 /// </summary>
391 /// <returns>An array of <see cref="MethodInfo"/> objects representing all methods
392 /// defined for the current Type.</returns>
393 public MethodInfo[] GetMethods()
394 {
395 return Type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
396 }
397
398 /// <summary>
399 /// Returns all the public methods of the current Type.
400 /// </summary>
401 /// <returns>An array of <see cref="MethodInfo"/> objects representing all the public methods
402 /// defined for the current Type.</returns>
403 public MethodInfo[] GetPublicMethods()
404 {
405 return Type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
406 }
407
408 /// <summary>
409 /// Searches for the methods defined for the current Type,
410 /// using the specified binding constraints.
411 /// </summary>
412 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
413 /// that specify how the search is conducted.</param>
414 /// <returns>An array of <see cref="MethodInfo"/> objects representing all methods defined
415 /// for the current Type that match the specified binding constraints.</returns>
416 public MethodInfo[] GetMethods(BindingFlags flags)
417 {
418 return Type.GetMethods(flags);
419 }
420
421 /// <summary>
422 /// Returns all the generic or non-generic methods of the current Type.
423 /// </summary>
424 /// <param name="generic">True to return all generic methods, false to return all non-generic.</param>
425 /// <returns>An array of <see cref="MethodInfo"/> objects representing all methods
426 /// defined for the current Type.</returns>
427 public MethodInfo[] GetMethods(bool generic)
428 {
429 return GetMethods(Type, generic, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
430 }
431
432 /// <summary>
433 /// Returns all the public and non-generic methods of the current Type.
434 /// </summary>
435 /// <param name="generic">True to return all generic methods, false to return all non-generic.</param>
436 /// <returns>An array of <see cref="MethodInfo"/> objects representing all the public methods
437 /// defined for the current Type.</returns>
438 public MethodInfo[] GetPublicMethods(bool generic)
439 {
440 return GetMethods(Type, generic, BindingFlags.Instance | BindingFlags.Public);
441 }
442
443 /// <summary>
444 /// Searches for the generic methods defined for the current Type,
445 /// using the specified binding constraints.
446 /// </summary>
447 /// <param name="generic">True to return all generic methods, false to return all non-generic.</param>
448 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
449 /// that specify how the search is conducted.</param>
450 /// <returns>An array of <see cref="MethodInfo"/> objects representing all methods defined
451 /// for the current Type that match the specified binding constraints.</returns>
452 public MethodInfo[] GetMethods(bool generic, BindingFlags flags)
453 {
454 return GetMethods(Type, generic, flags);
455 }
456
457 #endregion
458
459 #region GetMethod
460
461 /// <summary>
462 /// Searches for the specified instance method (public or non-public), using the specified name.
463 /// </summary>
464 /// <param name="methodName">The String containing the name of the method to get.</param>
465 /// <returns>A <see cref="MethodInfo"/> object representing the method
466 /// that matches the specified name, if found; otherwise, null.</returns>
467 public MethodInfo GetMethod(string methodName)
468 {
469 return Type.GetMethod(methodName,
470 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
471 }
472
473 /// <summary>
474 /// Searches for the specified public instance method, using the specified name.
475 /// </summary>
476 /// <param name="methodName">The String containing the name of the method to get.</param>
477 /// <returns>A <see cref="MethodInfo"/> object representing the method
478 /// that matches the specified name, if found; otherwise, null.</returns>
479 public MethodInfo GetPublicMethod(string methodName)
480 {
481 return Type.GetMethod(methodName,
482 BindingFlags.Instance | BindingFlags.Public);
483 }
484
485 /// <summary>
486 /// Searches for the specified method, using the specified name and binding flags.
487 /// </summary>
488 /// <param name="methodName">The String containing the name of the method to get.</param>
489 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
490 /// that specify how the search is conducted.</param>
491 /// <returns>A <see cref="MethodInfo"/> object representing the method
492 /// that matches the specified requirements, if found; otherwise, null.</returns>
493 public MethodInfo GetMethod(string methodName, BindingFlags flags)
494 {
495 return Type.GetMethod(methodName, flags);
496 }
497
498 /// <summary>
499 /// Searches for the specified public instance method, using the specified name.
500 /// </summary>
501 /// <param name="methodName">The String containing the name of the method to get.</param>
502 /// <param name="types">An array of <see cref="System.Type"/> objects representing
503 /// the number, order, and type of the parameters for the method to get.-or-
504 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
505 /// to get a method that takes no parameters.</param>
506 /// <returns>A <see cref="MethodInfo"/> object representing the method
507 /// that matches the specified requirements, if found; otherwise, null.</returns>
508 public MethodInfo GetPublicMethod(string methodName, params Type[] types)
509 {
510 return Type.GetMethod(
511 methodName,
512 BindingFlags.Instance | BindingFlags.Public,
513 null,
514 types,
515 null);
516 }
517
518 /// <summary>
519 /// Searches for the specified instance method (public or non-public),
520 /// using the specified name and argument types.
521 /// </summary>
522 /// <param name="methodName">The String containing the name of the method to get.</param>
523 /// <param name="types">An array of <see cref="System.Type"/> objects representing
524 /// the number, order, and type of the parameters for the method to get.-or-
525 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
526 /// to get a method that takes no parameters.</param>
527 /// <returns>A <see cref="MethodInfo"/> object representing the method
528 /// that matches the specified requirements, if found; otherwise, null.</returns>
529 public MethodInfo GetMethod(string methodName, params Type[] types)
530 {
531 return Type.GetMethod(
532 methodName,
533 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
534 null,
535 types,
536 null);
537 }
538
539 /// <summary>
540 /// Searches for the specified method, using the specified name,
541 /// binding flags and argument types.
542 /// </summary>
543 /// <param name="methodName">The String containing the name of the method to get.</param>
544 /// <param name="types">An array of <see cref="System.Type"/> objects representing
545 /// the number, order, and type of the parameters for the method to get.-or-
546 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
547 /// to get a method that takes no parameters.</param>
548 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
549 /// that specify how the search is conducted.</param>
550 /// <returns>A <see cref="MethodInfo"/> object representing the method
551 /// that matches the specified requirements, if found; otherwise, null.</returns>
552 public MethodInfo GetMethod(string methodName, BindingFlags flags, params Type[] types)
553 {
554 return Type.GetMethod(methodName, flags, null, types, null);
555 }
556
557 /// <summary>
558 /// Searches for the specified instance method (public or non-public), using the specified name.
559 /// </summary>
560 /// <param name="methodName">The String containing the name of the method to get.</param>
561 /// <param name="generic">True to search only for a generic method, or
562 /// False to search only for non-generic method.</param>
563 /// <returns>A <see cref="MethodInfo"/> object representing the method
564 /// that matches the specified requirements, if found; otherwise, null.</returns>
565 public MethodInfo GetMethod(bool generic, string methodName)
566 {
567 return GetMethod(Type, generic, methodName,
568 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
569 }
570
571 /// <summary>
572 /// Searches for the specified public instance method, using the specified name.
573 /// </summary>
574 /// <param name="methodName">The String containing the name of the method to get.</param>
575 /// <param name="generic">True to search only for a generic method, or
576 /// False to search only for non-generic method.</param>
577 /// <returns>A <see cref="MethodInfo"/> object representing the method
578 /// that matches the specified requirements, if found; otherwise, null.</returns>
579 public MethodInfo GetPublicMethod(bool generic, string methodName)
580 {
581 return GetMethod(Type, generic, methodName,
582 BindingFlags.Instance | BindingFlags.Public);
583 }
584
585 /// <summary>
586 /// Searches for the specified method, using the specified name and binding flags.
587 /// </summary>
588 /// <param name="methodName">The String containing the name of the method to get.</param>
589 /// <param name="generic">True to search only for a generic method, or
590 /// False to search only for non-generic method.</param>
591 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
592 /// that specify how the search is conducted.</param>
593 /// <returns>A <see cref="MethodInfo"/> object representing the method
594 /// that matches the specified requirements, if found; otherwise, null.</returns>
595 public MethodInfo GetMethod(bool generic, string methodName, BindingFlags flags)
596 {
597 return GetMethod(Type, generic, methodName, flags);
598 }
599
600 /// <summary>
601 /// Searches for the specified public instance method, using the specified name and argument types.
602 /// </summary>
603 /// <param name="methodName">The String containing the name of the method to get.</param>
604 /// <param name="generic">True to search only for a generic method, or
605 /// False to search only for non-generic method.</param>
606 /// <param name="types">An array of <see cref="System.Type"/> objects representing
607 /// the number, order, and type of the parameters for the method to get.-or-
608 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
609 /// to get a method that takes no parameters.</param>
610 /// <returns>A <see cref="MethodInfo"/> object representing the method
611 /// that matches the specified requirements, if found; otherwise, null.</returns>
612 public MethodInfo GetPublicMethod(bool generic, string methodName, params Type[] types)
613 {
614 return Type.GetMethod(methodName,
615 BindingFlags.Instance | BindingFlags.Public,
616 generic ? GenericBinder.Generic : GenericBinder.NonGeneric,
617 types, null);
618 }
619
620 /// <summary>
621 /// Searches for the specified instance method (public or non-public),
622 /// using the specified name and argument types.
623 /// </summary>
624 /// <param name="methodName">The String containing the name of the method to get.</param>
625 /// <param name="generic">True to search only for a generic method, or
626 /// False to search only for non-generic method.</param>
627 /// <param name="types">An array of <see cref="System.Type"/> objects representing
628 /// the number, order, and type of the parameters for the method to get.-or-
629 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
630 /// to get a method that takes no parameters.</param>
631 /// <returns>A <see cref="MethodInfo"/> object representing the method
632 /// that matches the specified requirements, if found; otherwise, null.</returns>
633 public MethodInfo GetMethod(bool generic, string methodName, params Type[] types)
634 {
635 return Type.GetMethod(methodName,
636 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
637 generic ? GenericBinder.Generic : GenericBinder.NonGeneric,
638 types, null);
639 }
640
641 /// <summary>
642 /// Searches for the specified method using the specified name, binding flags and argument types.
643 /// </summary>
644 /// <param name="methodName">The String containing the name of the method to get.</param>
645 /// <param name="generic">True to search only for a generic method, or
646 /// False to search only for non-generic method.</param>
647 /// <param name="types">An array of <see cref="System.Type"/> objects representing
648 /// the number, order, and type of the parameters for the method to get.-or-
649 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
650 /// to get a method that takes no parameters.</param>
651 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
652 /// that specify how the search is conducted.</param>
653 /// <returns>A <see cref="MethodInfo"/> object representing the method
654 /// that matches the specified requirements, if found; otherwise, null.</returns>
655 public MethodInfo GetMethod(bool generic, string methodName, BindingFlags flags, params Type[] types)
656 {
657 return Type.GetMethod(methodName,
658 flags,
659 generic ? GenericBinder.Generic : GenericBinder.NonGeneric,
660 types, null);
661 }
662
663 #endregion
664
665 #region GetFields
666
667 /// <summary>
668 /// Returns all the public fields of the current Type.
669 /// </summary>
670 /// <returns>An array of <see cref="FieldInfo"/> objects representing
671 /// all the public fields defined for the current Type.</returns>
672 public FieldInfo[] GetFields()
673 {
674 return Type.GetFields();
675 }
676
677 /// <summary>
678 /// Searches for the fields of the current Type, using the specified binding constraints.
679 /// </summary>
680 /// <param name="bindingFlags">A bitmask comprised of one or more <see cref="BindingFlags"/>
681 /// that specify how the search is conducted.</param>
682 /// <returns>An array of <see cref="FieldInfo"/> objects representing
683 /// all fields of the current Type
684 /// that match the specified binding constraints.</returns>
685 public FieldInfo[] GetFields(BindingFlags bindingFlags)
686 {
687 return Type.GetFields(bindingFlags);
688 }
689
690 /// <summary>
691 /// Searches for the public field with the specified name.
692 /// </summary>
693 /// <param name="name">The String containing the name of the public field to get.</param>
694 /// <returns>A <see cref="PropertyInfo"/> object representing the public field with the specified name,
695 /// if found; otherwise, a null reference.</returns>
696 public FieldInfo GetField(string name)
697 {
698 return Type.GetField(
699 name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
700 }
701
702 #endregion
703
704 #region GetProperties
705
706 /// <summary>
707 /// Returns all the public properties of the current Type.
708 /// </summary>
709 /// <returns>An array of <see cref="PropertyInfo"/> objects representing
710 /// all public properties of the current Type.</returns>
711 public PropertyInfo[] GetProperties()
712 {
713 return Type.GetProperties();
714 }
715
716 /// <summary>
717 /// Searches for the properties of the current Type, using the specified binding constraints.
718 /// </summary>
719 /// <param name="bindingFlags">A bitmask comprised of one or more <see cref="BindingFlags"/>
720 /// that specify how the search is conducted.</param>
721 /// <returns>An array of <see cref="PropertyInfo"/> objects representing
722 /// all properties of the current Type
723 /// that match the specified binding constraints.</returns>
724 public PropertyInfo[] GetProperties(BindingFlags bindingFlags)
725 {
726 return Type.GetProperties(bindingFlags);
727 }
728
729 /// <summary>
730 /// Searches for the public property with the specified name.
731 /// </summary>
732 /// <param name="name">The String containing the name of the public property to get.</param>
733 /// <returns>A <see cref="PropertyInfo"/> object representing the public property with the specified name,
734 /// if found; otherwise, a null reference.</returns>
735 public PropertyInfo GetProperty(string name)
736 {
737 return Type.GetProperty(
738 name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
739 }
740
741 #endregion
742
743 #region GetInterfaces
744
745 /*
746 private Type[] _interfaces;
747
748 /// <summary>
749 /// Gets all the interfaces implemented or inherited by the current <see cref="Type"/>.
750 /// </summary>
751 /// <returns>An array of Type objects representing all the interfaces implemented or
752 /// inherited by the current Type,
753 /// if found; otherwise, an empty array.</returns>
754 public Type[] GetInterfaces()
755 {
756 if (_interfaces == null)
757 _interfaces = _type.GetInterfaces();
758
759 return _interfaces;
760 }
761
762 /// <summary>
763 /// Gets a specific interface implemented or inherited by the current <see cref="Type"/>.
764 /// </summary>
765 /// <param name="interfaceType">The type of the interface to get.</param>
766 /// <returns>A Type object representing the interface of the specified type, if found;
767 /// otherwise, a null reference (Nothing in Visual Basic).</returns>
768 public Type GetInterface(Type interfaceType)
769 {
770 foreach (Type intf in GetInterfaces())
771 if (intf == interfaceType)
772 return null;
773
774 _type.IsSubclassOf(interfaceType);
775
776 return null;
777 }
778 */
779
780 /// <summary>
781 /// Returns an interface mapping for the current <see cref="Type"/>.
782 /// </summary>
783 /// <param name="interfaceType">The <see cref="System.Type"/>
784 /// of the interface of which to retrieve a mapping.</param>
785 /// <returns>An <see cref="InterfaceMapping"/> object representing the interface
786 /// mapping for <paramref name="interfaceType"/>.</returns>
787 public InterfaceMapping GetInterfaceMap(Type interfaceType)
788 {
789 return Type.GetInterfaceMap(interfaceType);
790 }
791
792 #endregion
793
794 #region GetConstructor
795
796 /// <summary>
797 /// Searches for a public instance constructor whose parameters match
798 /// the types in the specified array.
799 /// </summary>
800 /// <param name="types">An array of Type objects representing the number,
801 /// order, and type of the parameters for the constructor to get.</param>
802 /// <returns>A <see cref="ConstructorInfo"/> object representing the
803 /// public instance constructor whose parameters match the types in
804 /// the parameter type array, if found; otherwise, a null reference.</returns>
805 public ConstructorInfo GetPublicConstructor(params Type[] types)
806 {
807 return Type.GetConstructor(types);
808 }
809
810 /// <summary>
811 /// Searches for an instance constructor (public or non-public) whose
812 /// parameters match the types in the specified array.
813 /// </summary>
814 /// <param name="parameterType">Type object representing type of the
815 /// parameter for the constructor to get.</param>
816 /// <returns>A <see cref="ConstructorInfo"/> object representing the constructor
817 /// whose parameters match the types in the parameter type array, if found;
818 /// otherwise, a null reference.</returns>
819 public ConstructorInfo GetConstructor(Type parameterType)
820 {
821 return GetConstructor(Type, parameterType);
822 }
823
824 /// <summary>
825 /// Searches for an instance constructor (public or non-public) whose
826 /// parameters match the types in the specified array.
827 /// </summary>
828 /// <param name="type">An instance of <see cref="System.Type"/> to search constructor for.</param>
829 /// <param name="types">An array of Type objects representing the number,
830 /// order, and type of the parameters for the constructor to get.</param>
831 /// <returns>A <see cref="ConstructorInfo"/> object representing the constructor
832 /// whose parameters match the types in the parameter type array, if found;
833 /// otherwise, a null reference.</returns>
834 public static ConstructorInfo GetConstructor(Type type, params Type[] types)
835 {
836 if (type == null) throw new ArgumentNullException("type");
837
838 return type.GetConstructor(
839 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
840 null,
841 types,
842 null);
843 }
844
845 /// <summary>
846 /// Searches for a public default constructor.
847 /// </summary>
848 /// <returns>A <see cref="ConstructorInfo"/> object representing the constructor.</returns>
849 public ConstructorInfo GetPublicDefaultConstructor()
850 {
851 return Type.GetConstructor(Type.EmptyTypes);
852 }
853
854 /// <summary>
855 /// Searches for a default constructor.
856 /// </summary>
857 /// <returns>A <see cref="ConstructorInfo"/> object representing the constructor.</returns>
858 public ConstructorInfo GetDefaultConstructor()
859 {
860 return GetDefaultConstructor(Type);
861 }
862
863 /// <summary>
864 /// Searches for a default constructor.
865 /// </summary>
866 /// <param name="type">An instance of <see cref="System.Type"/> to search constructor for.</param>
867 /// <returns>A <see cref="ConstructorInfo"/> object representing the constructor.</returns>
868 public static ConstructorInfo GetDefaultConstructor(Type type)
869 {
870 if (type == null) throw new ArgumentNullException("type");
871
872 return type.GetConstructor(
873 BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
874 null,
875 Type.EmptyTypes,
876 null);
877 }
878
879 /// <summary>
880 /// Searches for a public constructors.
881 /// </summary>
882 /// <returns>An array of <see cref="ConstructorInfo"/> objects
883 /// representing all the type public constructors, if found; otherwise, an empty array.</returns>
884 public ConstructorInfo[] GetPublicConstructors()
885 {
886 return Type.GetConstructors();
887 }
888
889 /// <summary>
890 /// Searches for all constructors (except type constructors).
891 /// </summary>
892 /// <returns>An array of <see cref="ConstructorInfo"/> objects
893 /// representing all the type constructors, if found; otherwise, an empty array.</returns>
894 public ConstructorInfo[] GetConstructors()
895 {
896 return Type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
897 }
898
899 #endregion
900
901 #region Static Members
902
903 /// <summary>
904 /// Gets a value indicating whether a type (or type's element type)
905 /// instance can be null in the underlying data store.
906 /// </summary>
907 /// <param name="type">A <see cref="System.Type"/> instance. </param>
908 /// <returns> True, if the type parameter is a closed generic nullable type; otherwise, False.</returns>
909 /// <remarks>Arrays of Nullable types are treated as Nullable types.</remarks>
910 public static bool IsNullable(Type type)
911 {
912 while (type.IsArray)
913 type = type.GetElementType();
914
915 return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
916 }
917
918 public static bool IsNullableType(Type type)
919 {
920 return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));
921 }
922
923 public static bool IsNullableEnum(Type type)
924 {
925 return IsNullableType(type) && type.GetGenericArguments()[0].IsEnum;
926 }
927
928 public static bool IsEnumOrNullableEnum(Type type)
929 {
930 return type.IsEnum || IsNullableEnum(type);
931 }
932
933 public static Type ToNullable(Type type)
934 {
935 if (!IsNullable(type) && type.IsValueType)
936 {
937 var nullable = typeof(Nullable<>);
938 var typeArguments = nullable.GetGenericArguments();
939 if (typeArguments != null && typeArguments.Length == 1)
940 {
941 type = nullable.MakeGenericType(type);
942 }
943 }
944 return type;
945 }
946
947 /// <summary>
948 /// Returns the underlying type argument of the specified type.
949 /// </summary>
950 /// <param name="type">A <see cref="System.Type"/> instance. </param>
951 /// <returns><list>
952 /// <item>The type argument of the type parameter,
953 /// if the type parameter is a closed generic nullable type.</item>
954 /// <item>The underlying Type if the type parameter is an enum type.</item>
955 /// <item>Otherwise, the type itself.</item>
956 /// </list>
957 /// </returns>
958 public static Type GetUnderlyingType(Type type)
959 {
960 if (type == null) throw new ArgumentNullException("type");
961
962 if (IsNullableType(type))
963 type = type.GetGenericArguments()[0];
964
965 if (type.IsEnum)
966 type = Enum.GetUnderlyingType(type);
967
968 return type;
969 }
970
971 public static Type UnwrapNullableType(Type type)
972 {
973 if (type == null) throw new ArgumentNullException("type");
974
975 return IsNullableType(type) ? type.GetGenericArguments()[0] : type;
976 }
977
978 public static IEnumerable<Type> GetDefiningTypes(Type child, MemberInfo member)
979 {
980 if (member.MemberType == MemberTypes.Property)
981 {
982 var prop = (PropertyInfo)member;
983 member = prop.GetGetMethod();
984 }
985
986 foreach (var inf in child.GetInterfaces())
987 {
988 var pm = child.GetInterfaceMap(inf);
989
990 for (var i = 0; i < pm.TargetMethods.Length; i++)
991 {
992 var method = pm.TargetMethods[i];
993
994 if (method == member || (method.DeclaringType == member.DeclaringType && method.Name == member.Name))
995 yield return inf;
996 }
997 }
998
999 yield return member.DeclaringType;
1000 }
1001
1002 public static bool IsAbstractClass(Type type)
1003 {
1004 return type.IsClass && type.IsAbstract;
1005 }
1006
1007 /// <summary>
1008 /// Determines whether the specified types are considered equal.
1009 /// </summary>
1010 /// <param name="parent">A <see cref="System.Type"/> instance. </param>
1011 /// <param name="child">A type possible derived from the <c>parent</c> type</param>
1012 /// <returns>True, when an object instance of the type <c>child</c>
1013 /// can be used as an object of the type <c>parent</c>; otherwise, false.</returns>
1014 /// <remarks>Note that nullable types does not have a parent-child relation to it's underlying type.
1015 /// For example, the 'int?' type (nullable int) and the 'int' type
1016 /// aren't a parent and it's child.</remarks>
1017 public static bool IsSameOrParent([JetBrains.Annotations.NotNull] Type parent, [JetBrains.Annotations.NotNull] Type child)
1018 {
1019 if (parent == null) throw new ArgumentNullException("parent");
1020 if (child == null) throw new ArgumentNullException("child");
1021
1022 if (parent == child ||
1023 child.IsEnum && Enum.GetUnderlyingType(child) == parent ||
1024 child.IsSubclassOf(parent))
1025 {
1026 return true;
1027 }
1028
1029 if (parent.IsGenericTypeDefinition)
1030 for (var t = child; t != typeof(object) && t != null; t = t.BaseType)
1031 if (t.IsGenericType && t.GetGenericTypeDefinition() == parent)
1032 return true;
1033
1034 if (parent.IsInterface)
1035 {
1036 var interfaces = child.GetInterfaces();
1037
1038 foreach (var t in interfaces)
1039 {
1040 if (parent.IsGenericTypeDefinition)
1041 {
1042 if (t.IsGenericType && t.GetGenericTypeDefinition() == parent)
1043 return true;
1044 }
1045 else if (t == parent)
1046 return true;
1047 }
1048 }
1049
1050 return false;
1051 }
1052
1053 public static Type GetGenericType([JetBrains.Annotations.NotNull] Type genericType, Type type)
1054 {
1055 if (genericType == null) throw new ArgumentNullException("genericType");
1056
1057 while (type != null && type != typeof(object))
1058 {
1059 if (type.IsGenericType && type.GetGenericTypeDefinition() == genericType)
1060 return type;
1061
1062 if (genericType.IsInterface)
1063 {
1064 foreach (var interfaceType in type.GetInterfaces())
1065 {
1066 var gType = GetGenericType(genericType, interfaceType);
1067
1068 if (gType != null)
1069 return gType;
1070 }
1071 }
1072
1073 type = type.BaseType;
1074 }
1075
1076 return null;
1077 }
1078
1079 /// <summary>
1080 /// Searches for the method defined for a <see cref="System.Type"/>,
1081 /// using the specified name and binding flags.
1082 /// </summary>
1083 /// <param name="methodName">The String containing the name of the method to get.</param>
1084 /// <param name="generic">True to search only for a generic method, or
1085 /// False to search only for non-generic method.</param>
1086 /// <param name="type">A <see cref="System.Type"/> instance. </param>
1087 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
1088 /// that specify how the search is conducted.</param>
1089 /// <returns>A <see cref="MethodInfo"/> object representing the method
1090 /// that matches the specified requirements, if found; otherwise, null.</returns>
1091 public static MethodInfo GetMethod([JetBrains.Annotations.NotNull] Type type, bool generic, string methodName, BindingFlags flags)
1092 {
1093 if (type == null) throw new ArgumentNullException("type");
1094
1095 foreach (var method in type.GetMethods(flags))
1096 if (method.IsGenericMethodDefinition == generic && method.Name == methodName)
1097 return method;
1098
1099 return null;
1100 }
1101
1102 /// <summary>
1103 /// Searches for the methods defined for a <see cref="System.Type"/>,
1104 /// using the specified name and binding flags.
1105 /// </summary>
1106 /// <param name="type">A <see cref="System.Type"/> instance. </param>
1107 /// <param name="generic">True to return all generic methods, false to return all non-generic.</param>
1108 /// <param name="flags">A bitmask comprised of one or more <see cref="BindingFlags"/>
1109 /// that specify how the search is conducted.</param>
1110 /// <returns>An array of <see cref="MethodInfo"/> objects representing all methods defined
1111 /// for the current Type that match the specified binding constraints.</returns>
1112 public static MethodInfo[] GetMethods(Type type, bool generic, BindingFlags flags)
1113 {
1114 if (type == null) throw new ArgumentNullException("type");
1115
1116 return type.GetMethods(flags).Where(method => method.IsGenericMethodDefinition == generic).ToArray();
1117 }
1118
1119 /// <summary>
1120 /// Searches for the method defined for a <see cref="System.Type"/>,
1121 /// using the specified name and binding flags.
1122 /// </summary>
1123 /// <param name="type">A <see cref="System.Type"/> instance. </param>
1124 /// <param name="methodName">The String containing the name of the method to get.</param>
1125 /// <param name="requiredParametersCount">Number of required (non optional)
1126 /// parameter types.</param>
1127 /// <param name="bindingFlags">A bitmask comprised of one or more <see cref="BindingFlags"/>
1128 /// that specify how the search is conducted.</param>
1129 /// <param name="parameterTypes">An array of <see cref="System.Type"/> objects representing
1130 /// the number, order, and type of the parameters for the method to get.-or-
1131 /// An empty array of the type <see cref="System.Type"/> (for example, <see cref="System.Type.EmptyTypes"/>)
1132 /// to get a method that takes no parameters.</param>
1133 /// <returns>A <see cref="MethodInfo"/> object representing the method
1134 /// that matches the specified requirements, if found; otherwise, null.</returns>
1135 public static MethodInfo GetMethod(
1136 Type type,
1137 string methodName,
1138 BindingFlags bindingFlags,
1139 int requiredParametersCount,
1140 params Type[] parameterTypes)
1141 {
1142 while (parameterTypes.Length >= requiredParametersCount)
1143 {
1144 var method = type.GetMethod(methodName, parameterTypes);
1145
1146 if (null != method)
1147 return method;
1148
1149 if (parameterTypes.Length == 0)
1150 break;
1151
1152 Array.Resize(ref parameterTypes, parameterTypes.Length - 1);
1153 }
1154
1155 return null;
1156 }
1157
1158 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
1159 public static object[] GetPropertyParameters(PropertyInfo propertyInfo)
1160 {
1161 if (propertyInfo == null) throw new ArgumentNullException("propertyInfo");
1162
1163 var attrs = propertyInfo.GetCustomAttributes(typeof(ParameterAttribute), true);
1164
1165 if (attrs != null && attrs.Length > 0)
1166 return ((ParameterAttribute)attrs[0]).Parameters;
1167
1168 attrs = propertyInfo.GetCustomAttributes(typeof(InstanceTypeAttribute), true);
1169
1170 if (attrs.Length > 0)
1171 return ((InstanceTypeAttribute)attrs[0]).Parameters;
1172
1173 attrs = new TypeHelper(
1174 propertyInfo.DeclaringType).GetAttributes(typeof(GlobalInstanceTypeAttribute));
1175
1176 foreach (GlobalInstanceTypeAttribute attr in attrs)
1177 if (IsSameOrParent(attr.PropertyType, propertyInfo.PropertyType))
1178 // if (attr.PropertyType == propertyInfo.PropertyType)
1179 return attr.Parameters;
1180
1181 return null;
1182 }
1183
1184 /// <summary>
1185 /// Searches for the property defined for a <see cref="System.Type"/>,
1186 /// using the specified name and parameter types.
1187 /// </summary>
1188 /// <param name="type">A <see cref="System.Type"/> instance. </param>
1189 /// <param name="propertyName">The String containing the name of the method to get.</param>
1190 /// <param name="types">An array of Type objects representing the number,
1191 /// order, and type of the parameters for the constructor to get.</param>
1192 /// <param name="returnType">The property return <see cref="System.Type"/>. </param>
1193 /// <returns>A <see cref="MethodInfo"/> object representing the method
1194 /// that matches the specified requirements, if found; otherwise, null.</returns>
1195 public static PropertyInfo GetPropertyInfo(
1196 Type type, string propertyName, Type returnType, Type[] types)
1197 {
1198 if (type == null) throw new ArgumentNullException("type");
1199
1200 return type.GetProperty(
1201 propertyName,
1202 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
1203 null,
1204 returnType,
1205 types,
1206 null);
1207 }
1208
1209 ///<summary>
1210 /// Gets the Type of a list item.
1211 ///</summary>
1212 /// <param name="list">A <see cref="System.Object"/> instance. </param>
1213 ///<returns>The Type instance that represents the exact runtime type of a list item.</returns>
1214 public static Type GetListItemType(object list)
1215 {
1216 var typeOfObject = typeof(object);
1217
1218 if (list == null)
1219 return typeOfObject;
1220
1221 #if !SILVERLIGHT && !DATA
1222
1223 if (list is EditableArrayList)
1224 return ((EditableArrayList)list).ItemType;
1225
1226 #endif
1227
1228 if (list is Array)
1229 return list.GetType().GetElementType();
1230
1231 var type = list.GetType();
1232
1233 // object[] attrs = type.GetCustomAttributes(typeof(DefaultMemberAttribute), true);
1234 // string itemMemberName = (attrs.Length == 0)? "Item": ((DefaultMemberAttribute)attrs[0]).MemberName;
1235
1236 if (list is IList
1237 #if !SILVERLIGHT
1238 || list is ITypedList || list is IListSource
1239 #endif
1240 )
1241 {
1242 PropertyInfo last = null;
1243
1244 foreach (var pi in type.GetProperties())
1245 {
1246 if (pi.GetIndexParameters().Length > 0 && pi.PropertyType != typeOfObject)
1247 {
1248 if (pi.Name == "Item")
1249 return pi.PropertyType;
1250
1251 last = pi;
1252 }
1253 }
1254
1255 if (last != null)
1256 return last.PropertyType;
1257 }
1258
1259 try
1260 {
1261 if (list is IList)
1262 {
1263 foreach (var o in (IList)list)
1264 if (o != null && o.GetType() != typeOfObject)
1265 return o.GetType();
1266 }
1267 else if (list is IEnumerable)
1268 {
1269 foreach (var o in (IEnumerable)list)
1270 if (o != null && o.GetType() != typeOfObject)
1271 return o.GetType();
1272 }
1273 }
1274 catch
1275 {
1276 }
1277
1278 return typeOfObject;
1279 }
1280
1281 ///<summary>
1282 /// Gets the Type of a list item.
1283 ///</summary>
1284 /// <param name="listType">A <see cref="System.Type"/> instance. </param>
1285 ///<returns>The Type instance that represents the exact runtime type of a list item.</returns>
1286 public static Type GetListItemType(Type listType)
1287 {
1288 if (listType.IsGenericType)
1289 {
1290 var elementTypes = GetGenericArguments(listType, typeof(IList));
1291
1292 if (elementTypes != null)
1293 return elementTypes[0];
1294 }
1295
1296 if (IsSameOrParent(typeof(IList), listType)
1297 #if !SILVERLIGHT
1298 || IsSameOrParent(typeof(ITypedList), listType)
1299 || IsSameOrParent(typeof(IListSource), listType)
1300 #endif
1301 )
1302 {
1303 var elementType = listType.GetElementType();
1304
1305 if (elementType != null)
1306 return elementType;
1307
1308 PropertyInfo last = null;
1309
1310 foreach (var pi in listType.GetProperties())
1311 {
1312 if (pi.GetIndexParameters().Length > 0 && pi.PropertyType != typeof(object))
1313 {
1314 if (pi.Name == "Item")
1315 return pi.PropertyType;
1316
1317 last = pi;
1318 }
1319 }
1320
1321 if (last != null)
1322 return last.PropertyType;
1323 }
1324
1325 return typeof(object);
1326 }
1327
1328 public static Type GetElementType(Type type)
1329 {
1330 if (type == null)
1331 return null;
1332
1333 if (type == typeof(object))
1334 return type.HasElementType ? type.GetElementType(): null;
1335
1336 if (type.IsArray)
1337 return type.GetElementType();
1338
1339 if (type.IsGenericType)
1340 foreach (var aType in type.GetGenericArguments())
1341 if (typeof(IEnumerable<>).MakeGenericType(new[] { aType }).IsAssignableFrom(type))
1342 return aType;
1343
1344 var interfaces = type.GetInterfaces();
1345
1346 if (interfaces != null && interfaces.Length > 0)
1347 {
1348 foreach (var iType in interfaces)
1349 {
1350 var eType = GetElementType(iType);
1351
1352 if (eType != null)
1353 return eType;
1354 }
1355 }
1356
1357 return GetElementType(type.BaseType);
1358 }
1359
1360 /// <summary>
1361 /// Gets a value indicating whether a type can be used as a db primitive.
1362 /// </summary>
1363 /// <param name="type">A <see cref="System.Type"/> instance. </param>
1364 /// <returns> True, if the type parameter is a primitive type; otherwise, False.</returns>
1365 /// <remarks><see cref="System.String"/>. <see cref="Stream"/>.
1366 /// <see cref="XmlReader"/>. <see cref="XmlDocument"/>. are specially handled by the library
1367 /// and, therefore, can be treated as scalar types.</remarks>
1368 public static bool IsScalar(Type type)
1369 {
1370 while (type.IsArray)
1371 type = type.GetElementType();
1372
1373 return type.IsValueType
1374 || type == typeof(string)
1375 || type == typeof(System.Data.Linq.Binary)
1376 || type == typeof(Stream)
1377 || type == typeof(XmlReader)
1378 || type.GetCustomAttributes(typeof(ScalarAttribute),true).Any() // If the type is a UDT pass it as is
1379 #if !SILVERLIGHT
1380 || type == typeof(XmlDocument)
1381 || type == typeof(XElement)
1382 #endif
1383 ;
1384 }
1385
1386 ///<summary>
1387 /// Returns an array of Type objects that represent the type arguments
1388 /// of a generic type or the type parameters of a generic type definition.
1389 ///</summary>
1390 /// <param name="type">A <see cref="System.Type"/> instance.</param>
1391 ///<param name="baseType">Non generic base type.</param>
1392 ///<returns>An array of Type objects that represent the type arguments
1393 /// of a generic type. Returns an empty array if the current type is not a generic type.</returns>
1394 public static Type[] GetGenericArguments(Type type, Type baseType)
1395 {
1396 var baseTypeName = baseType.Name;
1397
1398 for (var t = type; t != typeof(object) && t != null; t = t.BaseType)
1399 {
1400 if (t.IsGenericType)
1401 {
1402 if (baseType.IsGenericTypeDefinition)
1403 {
1404 if (t.GetGenericTypeDefinition() == baseType)
1405 return t.GetGenericArguments();
1406 }
1407 else if (baseTypeName == null || t.Name.Split('`')[0] == baseTypeName)
1408 {
1409 return t.GetGenericArguments();
1410 }
1411 }
1412 }
1413
1414 foreach (var t in type.GetInterfaces())
1415 {
1416 if (t.IsGenericType)
1417 {
1418 if (baseType.IsGenericTypeDefinition)
1419 {
1420 if (t.GetGenericTypeDefinition() == baseType)
1421 return t.GetGenericArguments();
1422 }
1423 else if (baseTypeName == null || t.Name.Split('`')[0] == baseTypeName)
1424 {
1425 return t.GetGenericArguments();
1426 }
1427 }
1428 }
1429
1430 return null;
1431 }
1432
1433 /// <summary>
1434 /// Substitutes the elements of an array of types for the type parameters
1435 /// of the current generic type definition and returns a Type object
1436 /// representing the resulting constructed type.
1437 /// </summary>
1438 /// <param name="type">A <see cref="System.Type"/> instance.</param>
1439 /// <param name="typeArguments">An array of types to be substituted for
1440 /// the type parameters of the current generic type.</param>
1441 /// <returns>A Type representing the constructed type formed by substituting
1442 /// the elements of <paramref name="typeArguments"/> for the type parameters
1443 /// of the current generic type.</returns>
1444 /// <seealso cref="System.Type.MakeGenericType"/>
1445 public static Type TranslateGenericParameters(Type type, Type[] typeArguments)
1446 {
1447 // 'T paramName' case
1448 //
1449 if (type.IsGenericParameter)
1450 return typeArguments[type.GenericParameterPosition];
1451
1452 // 'List<T> paramName' or something like that.
1453 //
1454 if (type.IsGenericType && type.ContainsGenericParameters)
1455 {
1456 var genArgs = type.GetGenericArguments();
1457
1458 for (var i = 0; i < genArgs.Length; ++i)
1459 genArgs[i] = TranslateGenericParameters(genArgs[i], typeArguments);
1460
1461 return type.GetGenericTypeDefinition().MakeGenericType(genArgs);
1462 }
1463
1464 // Non-generic type.
1465 //
1466 return type;
1467 }
1468
1469 public static bool CompareParameterTypes(Type goal, Type probe)
1470 {
1471 if (goal == probe)
1472 return true;
1473
1474 if (goal.IsGenericParameter)
1475 return CheckConstraints(goal, probe);
1476 if (goal.IsGenericType && probe.IsGenericType)
1477 return CompareGenericTypes(goal, probe);
1478
1479 return false;
1480 }
1481
1482 public static bool CheckConstraints(Type goal, Type probe)
1483 {
1484 var constraints = goal.GetGenericParameterConstraints();
1485
1486 for (var i = 0; i < constraints.Length; i++)
1487 if (!constraints[i].IsAssignableFrom(probe))
1488 return false;
1489
1490 return true;
1491 }
1492
1493 public static bool CompareGenericTypes(Type goal, Type probe)
1494 {
1495 var genArgs = goal.GetGenericArguments();
1496 var specArgs = probe.GetGenericArguments();
1497 var match = (genArgs.Length == specArgs.Length);
1498
1499 for (var i = 0; match && i < genArgs.Length; i++)
1500 {
1501 if (genArgs[i] == specArgs[i])
1502 continue;
1503
1504 if (genArgs[i].IsGenericParameter)
1505 match = CheckConstraints(genArgs[i], specArgs[i]);
1506 else if (genArgs[i].IsGenericType && specArgs[i].IsGenericType)
1507 match = CompareGenericTypes(genArgs[i], specArgs[i]);
1508 else
1509 match = false;
1510 }
1511
1512 return match;
1513 }
1514
1515 public static PropertyInfo GetPropertyByMethod(MethodInfo method)
1516 {
1517 if (method != null)
1518 {
1519 var type = method.DeclaringType;
1520 var attr = BindingFlags.NonPublic | BindingFlags.Public | (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance);
1521
1522 foreach (var info in type.GetProperties(attr))
1523 {
1524 if (info.CanRead && method == info.GetGetMethod(true))
1525 return info;
1526
1527 if (info.CanWrite && method == info.GetSetMethod(true))
1528 return info;
1529 }
1530 }
1531
1532 return null;
1533 }
1534
1535 public static Type GetMemberType(MemberInfo memberInfo)
1536 {
1537 switch (memberInfo.MemberType)
1538 {
1539 case MemberTypes.Property : return ((PropertyInfo) memberInfo).PropertyType;
1540 case MemberTypes.Field : return ((FieldInfo) memberInfo).FieldType;
1541 case MemberTypes.Method : return ((MethodInfo) memberInfo).ReturnType;
1542 case MemberTypes.Constructor : return ((ConstructorInfo)memberInfo).DeclaringType;
1543 }
1544
1545 throw new InvalidOperationException();
1546 }
1547
1548 public static bool IsFloatType(Type type)
1549 {
1550 if (IsNullableType(type))
1551 type = type.GetGenericArguments()[0];
1552
1553 switch (Type.GetTypeCode(type))
1554 {
1555 case TypeCode.Single :
1556 case TypeCode.Double :
1557 case TypeCode.Decimal : return true;
1558 }
1559
1560 return false;
1561 }
1562
1563 public static bool IsIntegerType(Type type)
1564 {
1565 if (IsNullableType(type))
1566 type = type.GetGenericArguments()[0];
1567
1568 switch (Type.GetTypeCode(type))
1569 {
1570 case TypeCode.SByte :
1571 case TypeCode.Byte :
1572 case TypeCode.Int16 :
1573 case TypeCode.UInt16 :
1574 case TypeCode.Int32 :
1575 case TypeCode.UInt32 :
1576 case TypeCode.Int64 :
1577 case TypeCode.UInt64 : return true;
1578 }
1579
1580 return false;
1581 }
1582
1583 public static bool IsNullableValueMember(MemberInfo member)
1584 {
1585 return
1586 member.Name == "Value" &&
1587 member.DeclaringType.IsGenericType &&
1588 member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable<>);
1589 }
1590
1591 public static bool IsNullableHasValueMember(MemberInfo member)
1592 {
1593 return
1594 member.Name == "HasValue" &&
1595 member.DeclaringType.IsGenericType &&
1596 member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable<>);
1597 }
1598
1599 public static bool Equals(MemberInfo member1, MemberInfo member2)
1600 {
1601 return Equals(member1, member2, null);
1602 }
1603
1604 public static bool Equals(MemberInfo member1, MemberInfo member2, Type declaringType)
1605 {
1606 if (ReferenceEquals(member1, member2))
1607 return true;
1608
1609 if (member1 == null || member2 == null)
1610 return false;
1611
1612 if (member1.Name == member2.Name)
1613 {
1614 if (member1.DeclaringType == member2.DeclaringType)
1615 return true;
1616
1617 if (member1 is PropertyInfo)
1618 {
1619 var isSubclass =
1620 IsSameOrParent(member1.DeclaringType, member2.DeclaringType) ||
1621 IsSameOrParent(member2.DeclaringType, member1.DeclaringType);
1622
1623 if (isSubclass)
1624 return true;
1625
1626 if (declaringType != null && member2.DeclaringType.IsInterface)
1627 {
1628 var getter1 = ((PropertyInfo)member1).GetGetMethod();
1629 var getter2 = ((PropertyInfo)member2).GetGetMethod();
1630
1631 var map = declaringType.GetInterfaceMap(member2.DeclaringType);
1632
1633 for (var i = 0; i < map.InterfaceMethods.Length; i++)
1634 if (getter2.Name == map.InterfaceMethods[i].Name && getter2.DeclaringType == map.InterfaceMethods[i].DeclaringType &&
1635 getter1.Name == map.TargetMethods [i].Name && getter1.DeclaringType == map.TargetMethods [i].DeclaringType)
1636 return true;
1637 }
1638 }
1639 }
1640
1641 if (member2.DeclaringType.IsInterface && member1.Name.EndsWith(member2.Name))
1642 {
1643 if (member1 is PropertyInfo)
1644 {
1645 var isSubclass = member2.DeclaringType.IsAssignableFrom(member1.DeclaringType);
1646
1647 if (isSubclass)
1648 {
1649 var getter1 = ((PropertyInfo)member1).GetGetMethod();
1650 var getter2 = ((PropertyInfo)member2).GetGetMethod();
1651
1652 var map = member1.DeclaringType.GetInterfaceMap(member2.DeclaringType);
1653
1654 for (var i = 0; i < map.InterfaceMethods.Length; i++)
1655 if ((getter2 == null || (getter2.Name == map.InterfaceMethods[i].Name && getter2.DeclaringType == map.InterfaceMethods[i].DeclaringType))
1656 &&
1657 (getter1 == null || (getter1.Name == map.InterfaceMethods[i].Name && getter1.DeclaringType == map.InterfaceMethods[i].DeclaringType))
1658 )
1659 {
1660 return true;
1661 }
1662 }
1663 }
1664 }
1665
1666 return false;
1667 }
1668
1669 interface IGetDefaultValueHelper
1670 {
1671 object GetDefaultValue();
1672 }
1673
1674 class GetDefaultValueHelper<T> : IGetDefaultValueHelper
1675 {
1676 public object GetDefaultValue()
1677 {
1678 return default(T);
1679 }
1680 }
1681
1682 public static object GetDefaultValue(Type type)
1683 {
1684 var dtype = typeof(GetDefaultValueHelper<>).MakeGenericType(type);
1685 var helper = (IGetDefaultValueHelper)Activator.CreateInstance(dtype);
1686
1687 return helper.GetDefaultValue();
1688 }
1689
1690 #endregion
1691 }
1692 }