Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Utilities\ReflectionUtils.cs

Symbol Coverage: 76.99% (271 of 352)

Branch Coverage: 75.81% (141 of 186)

Cyclomatic Complexity Avg: 2.71 Max:9

Code Lines: 335


L V Source
1
#region License
2
// Copyright (c) 2007 James Newton-King
3
//
4
// Permission is hereby granted, free of charge, to any person
5
// obtaining a copy of this software and associated documentation
6
// files (the "Software"), to deal in the Software without
7
// restriction, including without limitation the rights to use,
8
// copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the
10
// Software is furnished to do so, subject to the following
11
// conditions:
12
//
13
// The above copyright notice and this permission notice shall be
14
// included in all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
// OTHER DEALINGS IN THE SOFTWARE.
24
#endregion
25

  
26
using System;
27
using System.Collections.Generic;
28
using System.Reflection;
29
using System.Collections;
30
using System.Linq;
31
using System.Globalization;
32
using System.Runtime.Serialization.Formatters;
33

  
34
namespace Newtonsoft.Json.Utilities
35
{
36
  internal static class ReflectionUtils
37
  {
38
    public static Type GetObjectType(object v)
39
    {
40
 210719
      return (v != null) ? v.GetType() : null;
41
 210719
    }
42

  
43
    public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat)
44
    {
45
 16
      switch (assemblyFormat)
46
      {
47
        case FormatterAssemblyStyle.Simple:
48
 10
          return t.FullName + ", " + t.Assembly.GetName().Name;
49
        case FormatterAssemblyStyle.Full:
50
 6
          return t.AssemblyQualifiedName;
51
        default:
52
 0
          throw new ArgumentOutOfRangeException();
53
      }
54
 16
    }
55

  
56
    public static bool IsInstantiatableType(Type t)
57
    {
58
 20051
      ValidationUtils.ArgumentNotNull(t, "t");
59

  
60
 20051
      if (t.IsAbstract || t.IsInterface || t.IsArray || t.IsGenericTypeDefinition || t == typeof(void))
61
 0
        return false;
62

  
63
 20051
      if (!HasDefaultConstructor(t))
64
 0
        return false;
65

  
66
 20051
      return true;
67
 20051
    }
68

  
69
    public static bool HasDefaultConstructor(Type t)
70
    {
71
 20051
      return HasDefaultConstructor(t, false);
72
 20051
    }
73

  
74
    public static bool HasDefaultConstructor(Type t, bool nonPublic)
75
    {
76
 20360
      ValidationUtils.ArgumentNotNull(t, "t");
77

  
78
 20360
      if (t.IsValueType)
79
 46
        return true;
80

  
81
 20314
      return (GetDefaultConstructor(t, nonPublic) != null);
82
 20360
    }
83

  
84
    public static ConstructorInfo GetDefaultConstructor(Type t)
85
    {
86
 209
      return GetDefaultConstructor(t, false);
87
 209
    }
88

  
89
    public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
90
    {
91
 20523
      BindingFlags accessModifier = BindingFlags.Public;
92
      
93
 20523
      if (nonPublic)
94
 263
        accessModifier = accessModifier | BindingFlags.NonPublic;
95

  
96
 20523
      return t.GetConstructor(accessModifier | BindingFlags.Instance, null, new Type[0], null);
97
 20523
    }
98

  
99
    public static bool IsNullable(Type t)
100
    {
101
 20276
      ValidationUtils.ArgumentNotNull(t, "t");
102

  
103
 20276
      if (t.IsValueType)
104
 116
        return IsNullableType(t);
105

  
106
 20160
      return true;
107
 20276
    }
108

  
109
    public static bool IsNullableType(Type t)
110
    {
111
 40922
      ValidationUtils.ArgumentNotNull(t, "t");
112

  
113
 40922
      return (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
114
 40922
    }
115

  
116
    //public static bool IsValueTypeUnitializedValue(ValueType value)
117
    //{
118
    //  if (value == null)
119
    //    return true;
120

  
121
    //  return value.Equals(CreateUnitializedValue(value.GetType()));
122
    //}
123

  
124
    public static bool IsUnitializedValue(object value)
125
    {
126
 0
      if (value == null)
127
      {
128
 0
        return true;
129
      }
130
      else
131
      {
132
 0
        object unitializedValue = CreateUnitializedValue(value.GetType());
133
 0
        return value.Equals(unitializedValue);
134
      }
135
 0
    }
136

  
137
    public static object CreateUnitializedValue(Type type)
138
    {
139
 0
      ValidationUtils.ArgumentNotNull(type, "type");
140

  
141
 0
      if (type.IsGenericTypeDefinition)
142
 0
        throw new ArgumentException("Type {0} is a generic type definition and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, type), "type");
143

  
144
 0
      if (type.IsClass || type.IsInterface || type == typeof(void))
145
 0
        return null;
146
 0
      else if (type.IsValueType)
147
 0
        return Activator.CreateInstance(type);
148
      else
149
 0
        throw new ArgumentException("Type {0} cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, type), "type");
150
 0
    }
151

  
152
    public static bool IsPropertyIndexed(PropertyInfo property)
153
    {
154
 0
      ValidationUtils.ArgumentNotNull(property, "property");
155

  
156
 0
      return !CollectionUtils.IsNullOrEmpty<ParameterInfo>(property.GetIndexParameters());
157
 0
    }
158

  
159
    public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition)
160
    {
161
      Type implementingType;
162
 235
      return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType);
163
 235
    }
164

  
165
    public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType)
166
    {
167
 348
      ValidationUtils.ArgumentNotNull(type, "type");
168
 348
      ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition");
169

  
170
 348
      if (!genericInterfaceDefinition.IsInterface || !genericInterfaceDefinition.IsGenericTypeDefinition)
171
 0
        throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition));
172

  
173
 348
      if (type.IsInterface)
174
      {
175
 16
        if (type.IsGenericType)
176
        {
177
 13
          Type interfaceDefinition = type.GetGenericTypeDefinition();
178

  
179
 13
          if (genericInterfaceDefinition == interfaceDefinition)
180
          {
181
 4
            implementingType = type;
182
 4
            return true;
183
          }
184
        }
185
      }
186

  
187
 344
      foreach (Type i in type.GetInterfaces())
188
      {
189
 713
        if (i.IsGenericType)
190
        {
191
 344
          Type interfaceDefinition = i.GetGenericTypeDefinition();
192

  
193
 344
          if (genericInterfaceDefinition == interfaceDefinition)
194
          {
195
 94
            implementingType = i;
196
 94
            return true;
197
          }
198
        }
199
      }
200

  
201
 250
      implementingType = null;
202
 250
      return false;
203
 348
    }
204

  
205
    public static bool AssignableToTypeName(this Type type, string fullTypeName, out Type match)
206
    {
207
 813
      Type current = type;
208

  
209
 2713
      while (current != null)
210
      {
211
 1909
        if (string.Equals(current.FullName, fullTypeName, StringComparison.Ordinal))
212
        {
213
 9
          match = current;
214
 9
          return true;
215
        }
216

  
217
 1900
        current = current.BaseType;
218
      }
219

  
220
 804
      foreach (Type i in type.GetInterfaces())
221
      {
222
 1591
        if (string.Equals(i.Name, fullTypeName, StringComparison.Ordinal))
223
        {
224
 0
          match = type;
225
 0
          return true;
226
        }
227
      }
228

  
229
 804
      match = null;
230
 804
      return false;
231
 813
    }
232

  
233
    public static bool AssignableToTypeName(this Type type, string fullTypeName)
234
    {
235
      Type match;
236
 640
      return type.AssignableToTypeName(fullTypeName, out match);
237
 640
    }
238

  
239
    public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
240
    {
241
      Type implementingType;
242
 17
      return InheritsGenericDefinition(type, genericClassDefinition, out implementingType);
243
 17
    }
244

  
245
    public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType)
246
    {
247
 20069
      ValidationUtils.ArgumentNotNull(type, "type");
248
 20069
      ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition");
249

  
250
 20069
      if (!genericClassDefinition.IsClass || !genericClassDefinition.IsGenericTypeDefinition)
251
 0
        throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition));
252

  
253
 20069
      return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType);
254
 20069
    }
255

  
256
    private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType)
257
    {
258
 40147
      if (currentType.IsGenericType)
259
      {
260
 20067
        Type currentGenericClassDefinition = currentType.GetGenericTypeDefinition();
261

  
262
 20067
        if (genericClassDefinition == currentGenericClassDefinition)
263
        {
264
 2
          implementingType = currentType;
265
 2
          return true;
266
        }
267
      }
268

  
269
 40145
      if (currentType.BaseType == null)
270
      {
271
 20067
        implementingType = null;
272
 20067
        return false;
273
      }
274

  
275
 20078
      return InheritsGenericDefinitionInternal(currentType.BaseType, genericClassDefinition, out implementingType);
276
 40147
    }
277

  
278
    /// <summary>
279
    /// Gets the type of the typed collection's items.
280
    /// </summary>
281
    /// <param name="type">The type.</param>
282
    /// <returns>The type of the typed collection's items.</returns>
283
    public static Type GetCollectionItemType(Type type)
284
    {
285
 70
      ValidationUtils.ArgumentNotNull(type, "type");
286
      Type genericListType;
287

  
288
 70
      if (type.IsArray)
289
      {
290
 40
        return type.GetElementType();
291
      }
292
 30
      else if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out genericListType))
293
      {
294
 23
        if (genericListType.IsGenericTypeDefinition)
295
 0
          throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
296

  
297
 23
        return genericListType.GetGenericArguments()[0];
298
      }
299
 7
      else if (typeof(IEnumerable).IsAssignableFrom(type))
300
      {
301
 7
        return null;
302
      }
303
      else
304
      {
305
 0
        throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
306
      }
307
 70
    }
308

  
309
    public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
310
    {
311
 4
      ValidationUtils.ArgumentNotNull(dictionaryType, "type");
312

  
313
      Type genericDictionaryType;
314
 4
      if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out genericDictionaryType))
315
      {
316
 3
        if (genericDictionaryType.IsGenericTypeDefinition)
317
 0
          throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
318

  
319
 3
        Type[] dictionaryGenericArguments = genericDictionaryType.GetGenericArguments();
320

  
321
 3
        keyType = dictionaryGenericArguments[0];
322
 3
        valueType = dictionaryGenericArguments[1];
323
 3
        return;
324
      }
325
 1
      else if (typeof(IDictionary).IsAssignableFrom(dictionaryType))
326
      {
327
 1
        keyType = null;
328
 1
        valueType = null;
329
 1
        return;
330
      }
331
      else
332
      {
333
 0
        throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
334
      }
335
 4
    }
336

  
337
    public static Type GetDictionaryValueType(Type dictionaryType)
338
    {
339
      Type keyType;
340
      Type valueType;
341
 1
      GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
342

  
343
 1
      return valueType;
344
 1
    }
345

  
346
    public static Type GetDictionaryKeyType(Type dictionaryType)
347
    {
348
      Type keyType;
349
      Type valueType;
350
 1
      GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
351

  
352
 1
      return keyType;
353
 1
    }
354

  
355
    /// <summary>
356
    /// Tests whether the list's items are their unitialized value.
357
    /// </summary>
358
    /// <param name="list">The list.</param>
359
    /// <returns>Whether the list's items are their unitialized value</returns>
360
    public static bool ItemsUnitializedValue<T>(IList<T> list)
361
    {
362
 0
      ValidationUtils.ArgumentNotNull(list, "list");
363

  
364
 0
      Type elementType = GetCollectionItemType(list.GetType());
365

  
366
 0
      if (elementType.IsValueType)
367
      {
368
 0
        object unitializedValue = CreateUnitializedValue(elementType);
369

  
370
 0
        for (int i = 0; i < list.Count; i++)
371
        {
372
 0
          if (!list[i].Equals(unitializedValue))
373
 0
            return false;
374
        }
375
      }
376
 0
      else if (elementType.IsClass)
377
      {
378
 0
        for (int i = 0; i < list.Count; i++)
379
        {
380
 0
          object value = list[i];
381

  
382
 0
          if (value != null)
383
 0
            return false;
384
        }
385
      }
386
      else
387
      {
388
 0
        throw new Exception("Type {0} is neither a ValueType or a Class.".FormatWith(CultureInfo.InvariantCulture, elementType));
389
      }
390

  
391
 0
      return true;
392
 0
    }
393

  
394
    /// <summary>
395
    /// Gets the member's underlying type.
396
    /// </summary>
397
    /// <param name="member">The member.</param>
398
    /// <returns>The underlying type of the member.</returns>
399
    public static Type GetMemberUnderlyingType(MemberInfo member)
400
    {
401
 161795
      ValidationUtils.ArgumentNotNull(member, "member");
402

  
403
 161795
      switch (member.MemberType)
404
      {
405
        case MemberTypes.Field:
406
 20503
          return ((FieldInfo)member).FieldType;
407
        case MemberTypes.Property:
408
 141292
          return ((PropertyInfo)member).PropertyType;
409
        case MemberTypes.Event:
410
 0
          return ((EventInfo)member).EventHandlerType;
411
        default:
412
 0
          throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
413
      }
414
 161795
    }
415

  
416
    /// <summary>
417
    /// Determines whether the member is an indexed property.
418
    /// </summary>
419
    /// <param name="member">The member.</param>
420
    /// <returns>
421
    /// 	<c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
422
    /// </returns>
423
    public static bool IsIndexedProperty(MemberInfo member)
424
    {
425
 1725
      ValidationUtils.ArgumentNotNull(member, "member");
426

  
427
 1725
      PropertyInfo propertyInfo = member as PropertyInfo;
428

  
429
 1725
      if (propertyInfo != null)
430
 972
        return IsIndexedProperty(propertyInfo);
431
      else
432
 753
        return false;
433
 1725
    }
434

  
435
    /// <summary>
436
    /// Determines whether the property is an indexed property.
437
    /// </summary>
438
    /// <param name="property">The property.</param>
439
    /// <returns>
440
    /// 	<c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
441
    /// </returns>
442
    public static bool IsIndexedProperty(PropertyInfo property)
443
    {
444
 972
      ValidationUtils.ArgumentNotNull(property, "property");
445

  
446
 972
      return (property.GetIndexParameters().Length > 0);
447
 972
    }
448

  
449
    /// <summary>
450
    /// Gets the member's value on the object.
451
    /// </summary>
452
    /// <param name="member">The member.</param>
453
    /// <param name="target">The target object.</param>
454
    /// <returns>The member's value on the object.</returns>
455
    public static object GetMemberValue(MemberInfo member, object target)
456
    {
457
 32
      ValidationUtils.ArgumentNotNull(member, "member");
458
 32
      ValidationUtils.ArgumentNotNull(target, "target");
459

  
460
 32
      switch (member.MemberType)
461
      {
462
        case MemberTypes.Field:
463
 7
          return ((FieldInfo)member).GetValue(target);
464
        case MemberTypes.Property:
465
          try
466
          {
467
 25
            return ((PropertyInfo)member).GetValue(target, null);
468
          }
469
 0
          catch (TargetParameterCountException e)
470
          {
471
 0
            throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), e);
472
          }
473
        default:
474
 0
          throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, CultureInfo.InvariantCulture, member.Name), "member");
475
      }
476
 32
    }
477

  
478
    /// <summary>
479
    /// Sets the member's value on the target object.
480
    /// </summary>
481
    /// <param name="member">The member.</param>
482
    /// <param name="target">The target.</param>
483
    /// <param name="value">The value.</param>
484
    public static void SetMemberValue(MemberInfo member, object target, object value)
485
    {
486
 0
      ValidationUtils.ArgumentNotNull(member, "member");
487
 0
      ValidationUtils.ArgumentNotNull(target, "target");
488

  
489
 0
      switch (member.MemberType)
490
      {
491
        case MemberTypes.Field:
492
 0
          ((FieldInfo)member).SetValue(target, value);
493
 0
          break;
494
        case MemberTypes.Property:
495
 0
          ((PropertyInfo)member).SetValue(target, value, null);
496
 0
          break;
497
        default:
498
 0
          throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member");
499
      }
500
 0
    }
501

  
502
    /// <summary>
503
    /// Determines whether the specified MemberInfo can be read.
504
    /// </summary>
505
    /// <param name="member">The MemberInfo to determine whether can be read.</param>
506
    /// /// <param name="nonPublic">if set to <c>true</c> then allow the member to be gotten non-publicly.</param>
507
    /// <returns>
508
    /// 	<c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
509
    /// </returns>
510
    public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
511
    {
512
 598
      switch (member.MemberType)
513
      {
514
        case MemberTypes.Field:
515
 128
          FieldInfo fieldInfo = (FieldInfo)member;
516

  
517
 128
          if (nonPublic)
518
 21
            return true;
519
 107
          else if (fieldInfo.IsPublic)
520
 107
            return true;
521
 0
          return false;
522
        case MemberTypes.Property:
523
 470
          PropertyInfo propertyInfo = (PropertyInfo) member;
524

  
525
 470
          if (!propertyInfo.CanRead)
526
 2
            return false;
527
 468
          if (nonPublic)
528
 93
            return true;
529
 375
          return (propertyInfo.GetGetMethod(nonPublic) != null);
530
        default:
531
 0
          return false;
532
      }
533
 598
    }
534

  
535
    /// <summary>
536
    /// Determines whether the specified MemberInfo can be set.
537
    /// </summary>
538
    /// <param name="member">The MemberInfo to determine whether can be set.</param>
539
    /// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
540
    /// <returns>
541
    /// 	<c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
542
    /// </returns>
543
    public static bool CanSetMemberValue(MemberInfo member, bool nonPublic)
544
    {
545
 598
      switch (member.MemberType)
546
      {
547
        case MemberTypes.Field:
548
 128
          FieldInfo fieldInfo = (FieldInfo)member;
549

  
550
 128
          if (fieldInfo.IsInitOnly)
551
 3
            return false;
552
 125
          if (nonPublic)
553
 20
            return true;
554
 105
          else if (fieldInfo.IsPublic)
555
 105
            return true;
556
 0
          return false;
557
        case MemberTypes.Property:
558
 470
          PropertyInfo propertyInfo = (PropertyInfo)member;
559

  
560
 470
          if (!propertyInfo.CanWrite)
561
 99
            return false;
562
 371
          if (nonPublic)
563
 88
            return true;
564
 283
          return (propertyInfo.GetSetMethod(nonPublic) != null);
565
        default:
566
 0
          return false;
567
      }
568
 598
    }
569

  
570
    public static List<MemberInfo> GetFieldsAndProperties<T>(BindingFlags bindingAttr)
571
    {
572
 0
      return GetFieldsAndProperties(typeof(T), bindingAttr);
573
 0
    }
574

  
575
    public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
576
    {
577
 346
      List<MemberInfo> targetMembers = new List<MemberInfo>();
578

  
579
 346
      targetMembers.AddRange(GetFields(type, bindingAttr));
580
 346
      targetMembers.AddRange(GetProperties(type, bindingAttr));
581

  
582
      // for some reason .NET returns multiple members when overriding a generic member on a base class
583
      // http://forums.msdn.microsoft.com/en-US/netfxbcl/thread/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/
584
      // filter members to only return the override on the topmost class
585
      // update: I think this is fixed in .NET 3.5 SP1 - leave this in for now...
586
 346
      List<MemberInfo> distinctMembers = new List<MemberInfo>(targetMembers.Count);
587

  
588
 346
      var groupedMembers = targetMembers.GroupBy(m => m.Name).Select(g => new { Count = g.Count(), Members = g.Cast<MemberInfo>() });
589
 346
      foreach (var groupedMember in groupedMembers)
590
      {
591
 1723
        if (groupedMember.Count == 1)
592
        {
593
 1721
          distinctMembers.Add(groupedMember.Members.First());
594
        }
595
        else
596
        {
597
 2
          var members = groupedMember.Members.Where(m => !IsOverridenGenericMember(m, bindingAttr) || m.Name == "Item");
598

  
599
 2
          distinctMembers.AddRange(members);
600
        }
601
      }
602

  
603
 346
      return distinctMembers;
604
 346
    }
605

  
606
    private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
607
    {
608
 4
      if (memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property)
609
 0
        throw new ArgumentException("Member must be a field or property.");
610

  
611
 4
      Type declaringType = memberInfo.DeclaringType;
612
 4
      if (!declaringType.IsGenericType)
613
 0
        return false;
614
 4
      Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
615
 4
      if (genericTypeDefinition == null)
616
 0
        return false;
617
 4
      MemberInfo[] members = genericTypeDefinition.GetMember(memberInfo.Name, bindingAttr);
618
 4
      if (members.Length == 0)
619
 0
        return false;
620
 4
      Type memberUnderlyingType = GetMemberUnderlyingType(members[0]);
621
 4
      if (!memberUnderlyingType.IsGenericParameter)
622
 0
        return false;
623

  
624
 4
      return true;
625
 4
    }
626

  
627
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
628
    {
629
 257
      return GetAttribute<T>(attributeProvider, true);
630
 257
    }
631

  
632
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
633
    {
634
 4218
      T[] attributes = GetAttributes<T>(attributeProvider, inherit);
635

  
636
 4218
      return CollectionUtils.GetSingleItem(attributes, true);
637
 4218
    }
638

  
639
    public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
640
    {
641
 4218
      ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
642

  
643
 4218
      return (T[])attributeProvider.GetCustomAttributes(typeof(T), inherit);
644
 4218
    }
645

  
646
    public static string GetNameAndAssessmblyName(Type t)
647
    {
648
 0
      ValidationUtils.ArgumentNotNull(t, "t");
649

  
650
 0
      return t.FullName + ", " + t.Assembly.GetName().Name;
651
 0
    }
652

  
653
    public static Type MakeGenericType(Type genericTypeDefinition, params Type[] innerTypes)
654
    {
655
 12
      ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
656
 12
      ValidationUtils.ArgumentNotNullOrEmpty<Type>(innerTypes, "innerTypes");
657
 12
      ValidationUtils.ArgumentConditionTrue(genericTypeDefinition.IsGenericTypeDefinition, "genericTypeDefinition", "Type {0} is not a generic type definition.".FormatWith(CultureInfo.InvariantCulture, genericTypeDefinition));
658

  
659
 12
      return genericTypeDefinition.MakeGenericType(innerTypes);
660
 12
    }
661

  
662
    public static object CreateGeneric(Type genericTypeDefinition, Type innerType, params object[] args)
663
    {
664
 1
      return CreateGeneric(genericTypeDefinition, new [] { innerType }, args);
665
 1
    }
666

  
667
    public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, params object[] args)
668
    {
669
 1
      return CreateGeneric(genericTypeDefinition, innerTypes, (t, a) => CreateInstance(t, a.ToArray()), args);
670
 1
    }
671

  
672
    public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, Func<Type, IList<object>, object> instanceCreator, params object[] args)
673
    {
674
 4
      ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
675
 4
      ValidationUtils.ArgumentNotNullOrEmpty(innerTypes, "innerTypes");
676
 4
      ValidationUtils.ArgumentNotNull(instanceCreator, "createInstance");
677

  
678
 4
      Type specificType = MakeGenericType(genericTypeDefinition, innerTypes.ToArray());
679

  
680
 4
      return instanceCreator(specificType, args);
681
 4
    }
682

  
683
    public static bool IsCompatibleValue(object value, Type type)
684
    {
685
 0
      if (value == null)
686
 0
        return IsNullable(type);
687

  
688
 0
      if (type.IsAssignableFrom(value.GetType()))
689
 0
        return true;
690

  
691
 0
      return false;
692
 0
    }
693

  
694
     public static object CreateInstance(Type type, params object[] args)
695
     {
696
 6
       ValidationUtils.ArgumentNotNull(type, "type");
697

  
698
#if !PocketPC
699
 6
       return Activator.CreateInstance(type, args);
700
#else
701
       // CF doesn't have a Activator.CreateInstance overload that takes args
702
       // lame
703

  
704
       if (type.IsValueType && CollectionUtils.IsNullOrEmpty<object>(args))
705
         return Activator.CreateInstance(type);
706

  
707
       ConstructorInfo[] constructors = type.GetConstructors();
708
       ConstructorInfo match = constructors.Where(c =>
709
         {
710
           ParameterInfo[] parameters = c.GetParameters();
711
           if (parameters.Length != args.Length)
712
             return false;
713

  
714
           for (int i = 0; i < parameters.Length; i++)
715
           {
716
             ParameterInfo parameter = parameters[i];
717
             object value = args[i];
718

  
719
             if (!IsCompatibleValue(value, parameter.ParameterType))
720
               return false;
721
           }
722

  
723
           return true;
724
         }).FirstOrDefault();
725

  
726
       if (match == null)
727
         throw new Exception("Could not create '{0}' with given parameters.".FormatWith(CultureInfo.InvariantCulture, type));
728

  
729
       return match.Invoke(args);
730
#endif
731
 6
     }
732

  
733
    public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName)
734
    {
735
 13
      int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
736

  
737
 13
      if (assemblyDelimiterIndex != null)
738
      {
739
 12
        typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim();
740
 12
        assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim();
741
      }
742
      else
743
      {
744
 1
        typeName = fullyQualifiedTypeName;
745
 1
        assemblyName = null;
746
      }
747

  
748
 13
    }
749

  
750
    private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
751
    {
752
      // we need to get the first comma following all surrounded in brackets because of generic types
753
      // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
754
 13
      int scope = 0;
755
 13
      for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
756
      {
757
 957
        char current = fullyQualifiedTypeName[i];
758
 957
        switch (current)
759
        {
760
          case '[':
761
 5
            scope++;
762
 5
            break;
763
          case ']':
764
 5
            scope--;
765
 5
            break;
766
          case ',':
767
 25
            if (scope == 0)
768
 12
              return i;
769
 13
            break;
770
        }
771
      }
772

  
773
 1
      return null;
774
 13
    }
775

  
776
    public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
777
    {
778
 346
      ValidationUtils.ArgumentNotNull(targetType, "targetType");
779

  
780
 346
      List<MemberInfo> fieldInfos = new List<MemberInfo>(targetType.GetFields(bindingAttr));
781
      // Type.GetFields doesn't return inherited private fields
782
      // manually find private fields from base class
783
 346
      GetChildPrivateFields(fieldInfos, targetType, bindingAttr);
784

  
785
 346
      return fieldInfos.Cast<FieldInfo>();
786
 346
    }
787

  
788
    private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
789
    {
790
      // fix weirdness with private FieldInfos only being returned for the current Type
791
      // find base type fields and add them to result
792
 346
      if ((bindingAttr & BindingFlags.NonPublic) != 0)
793
      {
794
        // modify flags to not search for public fields
795
 174
        BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
796

  
797
 376
        while ((targetType = targetType.BaseType) != null)
798
        {
799
          // filter out protected fields
800
 202
          IEnumerable<MemberInfo> childPrivateFields =
801
 63
            targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate).Cast<MemberInfo>();
802

  
803
 202
          initialFields.AddRange(childPrivateFields);
804
        }
805
      }
806
 346
    }
807

  
808
    public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
809
    {
810
 346
      ValidationUtils.ArgumentNotNull(targetType, "targetType");
811

  
812
 346
      List<MemberInfo> propertyInfos = new List<MemberInfo>(targetType.GetProperties(bindingAttr));
813
 346
      GetChildPrivateProperties(propertyInfos, targetType, bindingAttr);
814

  
815
 346
      return propertyInfos.Cast<PropertyInfo>();
816
 346
    }
817

  
818
    public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
819
    {
820
 348
      return ((bindingAttr & flag) == flag)
821
 348
        ? bindingAttr ^ flag
822
 348
        : bindingAttr;
823
 348
    }
824

  
825
    private static void GetChildPrivateProperties(IList<MemberInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
826
    {
827
      // fix weirdness with private PropertyInfos only being returned for the current Type
828
      // find base type properties and add them to result
829
 346
      if ((bindingAttr & BindingFlags.NonPublic) != 0)
830
      {
831
        // modify flags to not search for public fields
832
 174
        BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
833

  
834
 376
        while ((targetType = targetType.BaseType) != null)
835
        {
836
 30
          foreach (PropertyInfo propertyInfo in targetType.GetProperties(nonPublicBindingAttr))
837
          {
838
 30
            PropertyInfo nonPublicProperty = propertyInfo;
839

  
840
            // have to test on name rather than reference because instances are different
841
            // depending on the type that GetProperties was called on
842
 30
            int index = initialProperties.IndexOf(p => p.Name == nonPublicProperty.Name);
843
 30
            if (index == -1)
844
            {
845
 14
              initialProperties.Add(nonPublicProperty);
846
            }
847
            else
848
            {
849
              // replace nonpublic properties for a child, but gotten from
850
              // the parent with the one from the child
851
              // the property gotten from the child will have access to private getter/setter
852
 16
              initialProperties[index] = nonPublicProperty;
853
            }
854
          }
855
        }
856
      }
857
 346
    }
858
  }
859
}