0
|
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 }
|