Mercurial > pub > bltoolkit
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 } |