~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.Globalization;
 
31
using System.Runtime.Serialization;
 
32
using System.Runtime.Serialization.Formatters;
 
33
using System.Text;
 
34
#if NETFX_CORE
 
35
using IConvertible = Newtonsoft.Json.Utilities.Convertible;
 
36
#endif
 
37
#if NETFX_CORE || PORTABLE
 
38
using ICustomAttributeProvider = Newtonsoft.Json.Utilities.CustomAttributeProvider;
 
39
#endif
 
40
#if NET20
 
41
using Newtonsoft.Json.Utilities.LinqBridge;
 
42
#else
 
43
using System.Linq;
 
44
#endif
 
45
using Newtonsoft.Json.Serialization;
 
46
 
 
47
namespace Newtonsoft.Json.Utilities
 
48
{
 
49
#if NETFX_CORE || PORTABLE
 
50
  internal enum MemberTypes
 
51
  {
 
52
    Property,
 
53
    Field,
 
54
    Event,
 
55
    Method,
 
56
    Other
 
57
  }
 
58
 
 
59
  internal class CustomAttributeProvider
 
60
  {
 
61
    private readonly object _underlyingObject;
 
62
 
 
63
    public CustomAttributeProvider(object o)
 
64
    {
 
65
      _underlyingObject = o;
 
66
    }
 
67
 
 
68
    public object UnderlyingObject
 
69
    {
 
70
      get { return _underlyingObject; }
 
71
    }
 
72
  }
 
73
#endif
 
74
 
 
75
#if NETFX_CORE
 
76
  internal enum TypeCode
 
77
  {
 
78
    Empty,
 
79
    Object,
 
80
    String,
 
81
    Char,
 
82
    Boolean,
 
83
    SByte,
 
84
    Int16,
 
85
    UInt16,
 
86
    Int32,
 
87
    Byte,
 
88
    UInt32,
 
89
    Int64,
 
90
    UInt64,
 
91
    Single,
 
92
    Double,
 
93
    DateTime,
 
94
    Decimal
 
95
  }
 
96
 
 
97
  [Flags]
 
98
  internal enum BindingFlags
 
99
  {
 
100
    Default = 0,
 
101
    IgnoreCase = 1,
 
102
    DeclaredOnly = 2,
 
103
    Instance = 4,
 
104
    Static = 8,
 
105
    Public = 16,
 
106
    NonPublic = 32,
 
107
    FlattenHierarchy = 64,
 
108
    InvokeMethod = 256,
 
109
    CreateInstance = 512,
 
110
    GetField = 1024,
 
111
    SetField = 2048,
 
112
    GetProperty = 4096,
 
113
    SetProperty = 8192,
 
114
    PutDispProperty = 16384,
 
115
    ExactBinding = 65536,
 
116
    PutRefDispProperty = 32768,
 
117
    SuppressChangeType = 131072,
 
118
    OptionalParamBinding = 262144,
 
119
    IgnoreReturn = 16777216
 
120
  }
 
121
#endif
 
122
 
 
123
  internal static class ReflectionUtils
 
124
  {
 
125
    public static readonly Type[] EmptyTypes;
 
126
 
 
127
    static ReflectionUtils()
 
128
    {
 
129
#if !(NETFX_CORE || PORTABLE)
 
130
      EmptyTypes = Type.EmptyTypes;
 
131
#else
 
132
      EmptyTypes = new Type[0];
 
133
#endif
 
134
    }
 
135
 
 
136
    public static ICustomAttributeProvider GetCustomAttributeProvider(this object o)
 
137
    {
 
138
#if !(NETFX_CORE || PORTABLE)
 
139
      return (ICustomAttributeProvider)o;
 
140
#else
 
141
      return new ICustomAttributeProvider(o);
 
142
#endif
 
143
    }
 
144
 
 
145
    public static bool IsVirtual(this PropertyInfo propertyInfo)
 
146
    {
 
147
      ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
 
148
 
 
149
      MethodInfo m = propertyInfo.GetGetMethod();
 
150
      if (m != null && m.IsVirtual)
 
151
        return true;
 
152
 
 
153
      m = propertyInfo.GetSetMethod();
 
154
      if (m != null && m.IsVirtual)
 
155
        return true;
 
156
 
 
157
      return false;
 
158
    }
 
159
 
 
160
    public static Type GetObjectType(object v)
 
161
    {
 
162
      return (v != null) ? v.GetType() : null;
 
163
    }
 
164
 
 
165
    public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat)
 
166
    {
 
167
      return GetTypeName(t, assemblyFormat, null);
 
168
    }
 
169
 
 
170
    public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, SerializationBinder binder)
 
171
    {
 
172
      string fullyQualifiedTypeName;
 
173
#if !(NET20 || NET35)
 
174
      if (binder != null)
 
175
      {
 
176
        string assemblyName, typeName;
 
177
        binder.BindToName(t, out assemblyName, out typeName);
 
178
        fullyQualifiedTypeName = typeName + (assemblyName == null ? "" : ", " + assemblyName);
 
179
      }
 
180
      else
 
181
      {
 
182
        fullyQualifiedTypeName = t.AssemblyQualifiedName;
 
183
      }
 
184
#else
 
185
      fullyQualifiedTypeName = t.AssemblyQualifiedName;
 
186
#endif
 
187
 
 
188
      switch (assemblyFormat)
 
189
      {
 
190
        case FormatterAssemblyStyle.Simple:
 
191
          return RemoveAssemblyDetails(fullyQualifiedTypeName);
 
192
        case FormatterAssemblyStyle.Full:
 
193
          return fullyQualifiedTypeName;
 
194
        default:
 
195
          throw new ArgumentOutOfRangeException();
 
196
      }
 
197
    }
 
198
 
 
199
    private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
 
200
    {
 
201
      StringBuilder builder = new StringBuilder();
 
202
 
 
203
      // loop through the type name and filter out qualified assembly details from nested type names
 
204
      bool writingAssemblyName = false;
 
205
      bool skippingAssemblyDetails = false;
 
206
      for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
 
207
      {
 
208
        char current = fullyQualifiedTypeName[i];
 
209
        switch (current)
 
210
        {
 
211
          case '[':
 
212
            writingAssemblyName = false;
 
213
            skippingAssemblyDetails = false;
 
214
            builder.Append(current);
 
215
            break;
 
216
          case ']':
 
217
            writingAssemblyName = false;
 
218
            skippingAssemblyDetails = false;
 
219
            builder.Append(current);
 
220
            break;
 
221
          case ',':
 
222
            if (!writingAssemblyName)
 
223
            {
 
224
              writingAssemblyName = true;
 
225
              builder.Append(current);
 
226
            }
 
227
            else
 
228
            {
 
229
              skippingAssemblyDetails = true;
 
230
            }
 
231
            break;
 
232
          default:
 
233
            if (!skippingAssemblyDetails)
 
234
              builder.Append(current);
 
235
            break;
 
236
        }
 
237
      }
 
238
 
 
239
      return builder.ToString();
 
240
    }
 
241
 
 
242
    public static bool IsInstantiatableType(Type t)
 
243
    {
 
244
      ValidationUtils.ArgumentNotNull(t, "t");
 
245
 
 
246
      if (t.IsAbstract() || t.IsInterface() || t.IsArray || t.IsGenericTypeDefinition() || t == typeof(void))
 
247
        return false;
 
248
 
 
249
      if (!HasDefaultConstructor(t))
 
250
        return false;
 
251
 
 
252
      return true;
 
253
    }
 
254
 
 
255
    public static bool HasDefaultConstructor(Type t)
 
256
    {
 
257
      return HasDefaultConstructor(t, false);
 
258
    }
 
259
 
 
260
    public static bool HasDefaultConstructor(Type t, bool nonPublic)
 
261
    {
 
262
      ValidationUtils.ArgumentNotNull(t, "t");
 
263
 
 
264
      if (t.IsValueType())
 
265
        return true;
 
266
 
 
267
      return (GetDefaultConstructor(t, nonPublic) != null);
 
268
    }
 
269
 
 
270
    public static ConstructorInfo GetDefaultConstructor(Type t)
 
271
    {
 
272
      return GetDefaultConstructor(t, false);
 
273
    }
 
274
 
 
275
    public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
 
276
    {
 
277
      BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
 
278
      if (nonPublic)
 
279
        bindingFlags = bindingFlags | BindingFlags.NonPublic;
 
280
 
 
281
      return t.GetConstructors(bindingFlags).SingleOrDefault(c => !c.GetParameters().Any());
 
282
    }
 
283
 
 
284
    public static bool IsNullable(Type t)
 
285
    {
 
286
      ValidationUtils.ArgumentNotNull(t, "t");
 
287
 
 
288
      if (t.IsValueType())
 
289
        return IsNullableType(t);
 
290
 
 
291
      return true;
 
292
    }
 
293
 
 
294
    public static bool IsNullableType(Type t)
 
295
    {
 
296
      ValidationUtils.ArgumentNotNull(t, "t");
 
297
 
 
298
      return (t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(Nullable<>));
 
299
    }
 
300
 
 
301
    public static Type EnsureNotNullableType(Type t)
 
302
    {
 
303
      return (IsNullableType(t))
 
304
        ? Nullable.GetUnderlyingType(t)
 
305
        : t;
 
306
    }
 
307
 
 
308
    public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition)
 
309
    {
 
310
      Type implementingType;
 
311
      return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType);
 
312
    }
 
313
 
 
314
    public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType)
 
315
    {
 
316
      ValidationUtils.ArgumentNotNull(type, "type");
 
317
      ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition");
 
318
 
 
319
      if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition())
 
320
        throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition));
 
321
 
 
322
      if (type.IsInterface())
 
323
      {
 
324
        if (type.IsGenericType())
 
325
        {
 
326
          Type interfaceDefinition = type.GetGenericTypeDefinition();
 
327
 
 
328
          if (genericInterfaceDefinition == interfaceDefinition)
 
329
          {
 
330
            implementingType = type;
 
331
            return true;
 
332
          }
 
333
        }
 
334
      }
 
335
 
 
336
      foreach (Type i in type.GetInterfaces())
 
337
      {
 
338
        if (i.IsGenericType())
 
339
        {
 
340
          Type interfaceDefinition = i.GetGenericTypeDefinition();
 
341
 
 
342
          if (genericInterfaceDefinition == interfaceDefinition)
 
343
          {
 
344
            implementingType = i;
 
345
            return true;
 
346
          }
 
347
        }
 
348
      }
 
349
 
 
350
      implementingType = null;
 
351
      return false;
 
352
    }
 
353
 
 
354
    public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
 
355
    {
 
356
      Type implementingType;
 
357
      return InheritsGenericDefinition(type, genericClassDefinition, out implementingType);
 
358
    }
 
359
 
 
360
    public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType)
 
361
    {
 
362
      ValidationUtils.ArgumentNotNull(type, "type");
 
363
      ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition");
 
364
 
 
365
      if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition())
 
366
        throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition));
 
367
 
 
368
      return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType);
 
369
    }
 
370
 
 
371
    private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType)
 
372
    {
 
373
      if (currentType.IsGenericType())
 
374
      {
 
375
        Type currentGenericClassDefinition = currentType.GetGenericTypeDefinition();
 
376
 
 
377
        if (genericClassDefinition == currentGenericClassDefinition)
 
378
        {
 
379
          implementingType = currentType;
 
380
          return true;
 
381
        }
 
382
      }
 
383
 
 
384
      if (currentType.BaseType() == null)
 
385
      {
 
386
        implementingType = null;
 
387
        return false;
 
388
      }
 
389
 
 
390
      return InheritsGenericDefinitionInternal(currentType.BaseType(), genericClassDefinition, out implementingType);
 
391
    }
 
392
 
 
393
    /// <summary>
 
394
    /// Gets the type of the typed collection's items.
 
395
    /// </summary>
 
396
    /// <param name="type">The type.</param>
 
397
    /// <returns>The type of the typed collection's items.</returns>
 
398
    public static Type GetCollectionItemType(Type type)
 
399
    {
 
400
      ValidationUtils.ArgumentNotNull(type, "type");
 
401
      Type genericListType;
 
402
 
 
403
      if (type.IsArray)
 
404
      {
 
405
        return type.GetElementType();
 
406
      }
 
407
      else if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out genericListType))
 
408
      {
 
409
        if (genericListType.IsGenericTypeDefinition())
 
410
          throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
 
411
 
 
412
        return genericListType.GetGenericArguments()[0];
 
413
      }
 
414
      else if (typeof(IEnumerable).IsAssignableFrom(type))
 
415
      {
 
416
        return null;
 
417
      }
 
418
      else
 
419
      {
 
420
        throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
 
421
      }
 
422
    }
 
423
 
 
424
    public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
 
425
    {
 
426
      ValidationUtils.ArgumentNotNull(dictionaryType, "type");
 
427
 
 
428
      Type genericDictionaryType;
 
429
      if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out genericDictionaryType))
 
430
      {
 
431
        if (genericDictionaryType.IsGenericTypeDefinition())
 
432
          throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
 
433
 
 
434
        Type[] dictionaryGenericArguments = genericDictionaryType.GetGenericArguments();
 
435
 
 
436
        keyType = dictionaryGenericArguments[0];
 
437
        valueType = dictionaryGenericArguments[1];
 
438
        return;
 
439
      }
 
440
      else if (typeof(IDictionary).IsAssignableFrom(dictionaryType))
 
441
      {
 
442
        keyType = null;
 
443
        valueType = null;
 
444
        return;
 
445
      }
 
446
      else
 
447
      {
 
448
        throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
 
449
      }
 
450
    }
 
451
 
 
452
    public static Type GetDictionaryValueType(Type dictionaryType)
 
453
    {
 
454
      Type keyType;
 
455
      Type valueType;
 
456
      GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
 
457
 
 
458
      return valueType;
 
459
    }
 
460
 
 
461
    public static Type GetDictionaryKeyType(Type dictionaryType)
 
462
    {
 
463
      Type keyType;
 
464
      Type valueType;
 
465
      GetDictionaryKeyValueTypes(dictionaryType, out keyType, out valueType);
 
466
 
 
467
      return keyType;
 
468
    }
 
469
 
 
470
    /// <summary>
 
471
    /// Gets the member's underlying type.
 
472
    /// </summary>
 
473
    /// <param name="member">The member.</param>
 
474
    /// <returns>The underlying type of the member.</returns>
 
475
    public static Type GetMemberUnderlyingType(MemberInfo member)
 
476
    {
 
477
      ValidationUtils.ArgumentNotNull(member, "member");
 
478
 
 
479
      switch (member.MemberType())
 
480
      {
 
481
        case MemberTypes.Field:
 
482
          return ((FieldInfo)member).FieldType;
 
483
        case MemberTypes.Property:
 
484
          return ((PropertyInfo)member).PropertyType;
 
485
        case MemberTypes.Event:
 
486
          return ((EventInfo)member).EventHandlerType;
 
487
        default:
 
488
          throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
 
489
      }
 
490
    }
 
491
 
 
492
    /// <summary>
 
493
    /// Determines whether the member is an indexed property.
 
494
    /// </summary>
 
495
    /// <param name="member">The member.</param>
 
496
    /// <returns>
 
497
    ///         <c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
 
498
    /// </returns>
 
499
    public static bool IsIndexedProperty(MemberInfo member)
 
500
    {
 
501
      ValidationUtils.ArgumentNotNull(member, "member");
 
502
 
 
503
      PropertyInfo propertyInfo = member as PropertyInfo;
 
504
 
 
505
      if (propertyInfo != null)
 
506
        return IsIndexedProperty(propertyInfo);
 
507
      else
 
508
        return false;
 
509
    }
 
510
 
 
511
    /// <summary>
 
512
    /// Determines whether the property is an indexed property.
 
513
    /// </summary>
 
514
    /// <param name="property">The property.</param>
 
515
    /// <returns>
 
516
    ///         <c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
 
517
    /// </returns>
 
518
    public static bool IsIndexedProperty(PropertyInfo property)
 
519
    {
 
520
      ValidationUtils.ArgumentNotNull(property, "property");
 
521
 
 
522
      return (property.GetIndexParameters().Length > 0);
 
523
    }
 
524
 
 
525
    /// <summary>
 
526
    /// Gets the member's value on the object.
 
527
    /// </summary>
 
528
    /// <param name="member">The member.</param>
 
529
    /// <param name="target">The target object.</param>
 
530
    /// <returns>The member's value on the object.</returns>
 
531
    public static object GetMemberValue(MemberInfo member, object target)
 
532
    {
 
533
      ValidationUtils.ArgumentNotNull(member, "member");
 
534
      ValidationUtils.ArgumentNotNull(target, "target");
 
535
 
 
536
      switch (member.MemberType())
 
537
      {
 
538
        case MemberTypes.Field:
 
539
          return ((FieldInfo)member).GetValue(target);
 
540
        case MemberTypes.Property:
 
541
          try
 
542
          {
 
543
            return ((PropertyInfo)member).GetValue(target, null);
 
544
          }
 
545
          catch (TargetParameterCountException e)
 
546
          {
 
547
            throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), e);
 
548
          }
 
549
        default:
 
550
          throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, CultureInfo.InvariantCulture, member.Name), "member");
 
551
      }
 
552
    }
 
553
 
 
554
    /// <summary>
 
555
    /// Sets the member's value on the target object.
 
556
    /// </summary>
 
557
    /// <param name="member">The member.</param>
 
558
    /// <param name="target">The target.</param>
 
559
    /// <param name="value">The value.</param>
 
560
    public static void SetMemberValue(MemberInfo member, object target, object value)
 
561
    {
 
562
      ValidationUtils.ArgumentNotNull(member, "member");
 
563
      ValidationUtils.ArgumentNotNull(target, "target");
 
564
 
 
565
      switch (member.MemberType())
 
566
      {
 
567
        case MemberTypes.Field:
 
568
          ((FieldInfo)member).SetValue(target, value);
 
569
          break;
 
570
        case MemberTypes.Property:
 
571
          ((PropertyInfo)member).SetValue(target, value, null);
 
572
          break;
 
573
        default:
 
574
          throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member");
 
575
      }
 
576
    }
 
577
 
 
578
    /// <summary>
 
579
    /// Determines whether the specified MemberInfo can be read.
 
580
    /// </summary>
 
581
    /// <param name="member">The MemberInfo to determine whether can be read.</param>
 
582
    /// /// <param name="nonPublic">if set to <c>true</c> then allow the member to be gotten non-publicly.</param>
 
583
    /// <returns>
 
584
    ///         <c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
 
585
    /// </returns>
 
586
    public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
 
587
    {
 
588
      switch (member.MemberType())
 
589
      {
 
590
        case MemberTypes.Field:
 
591
          FieldInfo fieldInfo = (FieldInfo)member;
 
592
 
 
593
          if (nonPublic)
 
594
            return true;
 
595
          else if (fieldInfo.IsPublic)
 
596
            return true;
 
597
          return false;
 
598
        case MemberTypes.Property:
 
599
          PropertyInfo propertyInfo = (PropertyInfo) member;
 
600
 
 
601
          if (!propertyInfo.CanRead)
 
602
            return false;
 
603
          if (nonPublic)
 
604
            return true;
 
605
          return (propertyInfo.GetGetMethod(nonPublic) != null);
 
606
        default:
 
607
          return false;
 
608
      }
 
609
    }
 
610
 
 
611
    /// <summary>
 
612
    /// Determines whether the specified MemberInfo can be set.
 
613
    /// </summary>
 
614
    /// <param name="member">The MemberInfo to determine whether can be set.</param>
 
615
    /// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
 
616
    /// <param name="canSetReadOnly">if set to <c>true</c> then allow the member to be set if read-only.</param>
 
617
    /// <returns>
 
618
    ///         <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
 
619
    /// </returns>
 
620
    public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly)
 
621
    {
 
622
      switch (member.MemberType())
 
623
      {
 
624
        case MemberTypes.Field:
 
625
          FieldInfo fieldInfo = (FieldInfo)member;
 
626
 
 
627
          if (fieldInfo.IsInitOnly && !canSetReadOnly)
 
628
            return false;
 
629
          if (nonPublic)
 
630
            return true;
 
631
          else if (fieldInfo.IsPublic)
 
632
            return true;
 
633
          return false;
 
634
        case MemberTypes.Property:
 
635
          PropertyInfo propertyInfo = (PropertyInfo)member;
 
636
 
 
637
          if (!propertyInfo.CanWrite)
 
638
            return false;
 
639
          if (nonPublic)
 
640
            return true;
 
641
          return (propertyInfo.GetSetMethod(nonPublic) != null);
 
642
        default:
 
643
          return false;
 
644
      }
 
645
    }
 
646
 
 
647
    public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
 
648
    {
 
649
      List<MemberInfo> targetMembers = new List<MemberInfo>();
 
650
 
 
651
      targetMembers.AddRange(GetFields(type, bindingAttr));
 
652
      targetMembers.AddRange(GetProperties(type, bindingAttr));
 
653
 
 
654
      // for some reason .NET returns multiple members when overriding a generic member on a base class
 
655
      // http://forums.msdn.microsoft.com/en-US/netfxbcl/thread/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/
 
656
      // filter members to only return the override on the topmost class
 
657
      // update: I think this is fixed in .NET 3.5 SP1 - leave this in for now...
 
658
      List<MemberInfo> distinctMembers = new List<MemberInfo>(targetMembers.Count);
 
659
 
 
660
      foreach (var groupedMember in targetMembers.GroupBy(m => m.Name))
 
661
      {
 
662
        int count = groupedMember.Count();
 
663
        IList<MemberInfo> members = groupedMember.ToList();
 
664
 
 
665
        if (count == 1)
 
666
        {
 
667
          distinctMembers.Add(members.First());
 
668
        }
 
669
        else
 
670
        {
 
671
          var resolvedMembers = members.Where(m => !IsOverridenGenericMember(m, bindingAttr) || m.Name == "Item");
 
672
 
 
673
          distinctMembers.AddRange(resolvedMembers);
 
674
        }
 
675
      }
 
676
 
 
677
      return distinctMembers;
 
678
    }
 
679
 
 
680
 
 
681
    private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
 
682
    {
 
683
      MemberTypes memberType = memberInfo.MemberType();
 
684
      if (memberType != MemberTypes.Field && memberType != MemberTypes.Property)
 
685
        throw new ArgumentException("Member must be a field or property.");
 
686
 
 
687
      Type declaringType = memberInfo.DeclaringType;
 
688
      if (!declaringType.IsGenericType())
 
689
        return false;
 
690
      Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
 
691
      if (genericTypeDefinition == null)
 
692
        return false;
 
693
      MemberInfo[] members = genericTypeDefinition.GetMember(memberInfo.Name, bindingAttr);
 
694
      if (members.Length == 0)
 
695
        return false;
 
696
      Type memberUnderlyingType = GetMemberUnderlyingType(members[0]);
 
697
      if (!memberUnderlyingType.IsGenericParameter)
 
698
        return false;
 
699
 
 
700
      return true;
 
701
    }
 
702
 
 
703
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
 
704
    {
 
705
      return GetAttribute<T>(attributeProvider, true);
 
706
    }
 
707
 
 
708
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
 
709
    {
 
710
      T[] attributes = GetAttributes<T>(attributeProvider, inherit);
 
711
 
 
712
      return (attributes != null) ? attributes.SingleOrDefault() : null;
 
713
    }
 
714
 
 
715
#if !(NETFX_CORE)
 
716
    public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
 
717
    {
 
718
      ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
 
719
 
 
720
      object provider;
 
721
 
 
722
#if !PORTABLE
 
723
      provider = attributeProvider;
 
724
#else
 
725
      provider = attributeProvider.UnderlyingObject;
 
726
#endif
 
727
 
 
728
      // http://hyperthink.net/blog/getcustomattributes-gotcha/
 
729
      // ICustomAttributeProvider doesn't do inheritance
 
730
 
 
731
      if (provider is Type)
 
732
        return (T[])((Type)provider).GetCustomAttributes(typeof(T), inherit);
 
733
 
 
734
      if (provider is Assembly)
 
735
        return (T[])Attribute.GetCustomAttributes((Assembly)provider, typeof(T));
 
736
 
 
737
      if (provider is MemberInfo)
 
738
        return (T[])Attribute.GetCustomAttributes((MemberInfo)provider, typeof(T), inherit);
 
739
 
 
740
#if !PORTABLE
 
741
      if (provider is Module)
 
742
        return (T[])Attribute.GetCustomAttributes((Module)provider, typeof(T), inherit);
 
743
#endif
 
744
 
 
745
      if (provider is ParameterInfo)
 
746
        return (T[])Attribute.GetCustomAttributes((ParameterInfo)provider, typeof(T), inherit);
 
747
 
 
748
#if !PORTABLE
 
749
      return (T[])attributeProvider.GetCustomAttributes(typeof(T), inherit);
 
750
#else
 
751
      throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
 
752
#endif
 
753
    }
 
754
#else
 
755
    public static T[] GetAttributes<T>(ICustomAttributeProvider attributeProvider, bool inherit) where T : Attribute
 
756
    {
 
757
      object provider = attributeProvider.UnderlyingObject;
 
758
 
 
759
      if (provider is Type)
 
760
        return ((Type)provider).GetTypeInfo().GetCustomAttributes<T>(inherit).ToArray();
 
761
 
 
762
      if (provider is Assembly)
 
763
        return ((Assembly)provider).GetCustomAttributes<T>().ToArray();
 
764
 
 
765
      if (provider is MemberInfo)
 
766
        return ((MemberInfo)provider).GetCustomAttributes<T>(inherit).ToArray();
 
767
 
 
768
      if (provider is Module)
 
769
        return ((Module)provider).GetCustomAttributes<T>().ToArray();
 
770
 
 
771
      if (provider is ParameterInfo)
 
772
        return ((ParameterInfo)provider).GetCustomAttributes<T>(inherit).ToArray();
 
773
 
 
774
      throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
 
775
    }
 
776
#endif
 
777
 
 
778
    public static Type MakeGenericType(Type genericTypeDefinition, params Type[] innerTypes)
 
779
    {
 
780
      ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
 
781
      ValidationUtils.ArgumentNotNullOrEmpty<Type>(innerTypes, "innerTypes");
 
782
      ValidationUtils.ArgumentConditionTrue(genericTypeDefinition.IsGenericTypeDefinition(), "genericTypeDefinition", "Type {0} is not a generic type definition.".FormatWith(CultureInfo.InvariantCulture, genericTypeDefinition));
 
783
 
 
784
      return genericTypeDefinition.MakeGenericType(innerTypes);
 
785
    }
 
786
 
 
787
    public static object CreateGeneric(Type genericTypeDefinition, Type innerType, params object[] args)
 
788
    {
 
789
      return CreateGeneric(genericTypeDefinition, new [] { innerType }, args);
 
790
    }
 
791
 
 
792
    public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, params object[] args)
 
793
    {
 
794
      return CreateGeneric(genericTypeDefinition, innerTypes, (t, a) => CreateInstance(t, a.ToArray()), args);
 
795
    }
 
796
 
 
797
    public static object CreateGeneric(Type genericTypeDefinition, IList<Type> innerTypes, Func<Type, IList<object>, object> instanceCreator, params object[] args)
 
798
    {
 
799
      ValidationUtils.ArgumentNotNull(genericTypeDefinition, "genericTypeDefinition");
 
800
      ValidationUtils.ArgumentNotNullOrEmpty(innerTypes, "innerTypes");
 
801
      ValidationUtils.ArgumentNotNull(instanceCreator, "createInstance");
 
802
 
 
803
      Type specificType = MakeGenericType(genericTypeDefinition, innerTypes.ToArray());
 
804
 
 
805
      return instanceCreator(specificType, args);
 
806
    }
 
807
 
 
808
     public static object CreateInstance(Type type, params object[] args)
 
809
     {
 
810
       ValidationUtils.ArgumentNotNull(type, "type");
 
811
 
 
812
#if !PocketPC
 
813
       return Activator.CreateInstance(type, args);
 
814
#else
 
815
       // CF doesn't have a Activator.CreateInstance overload that takes args
 
816
       // lame
 
817
 
 
818
       if (type.IsValueType && CollectionUtils.IsNullOrEmpty<object>(args))
 
819
         return Activator.CreateInstance(type);
 
820
 
 
821
       ConstructorInfo[] constructors = type.GetConstructors();
 
822
       ConstructorInfo match = constructors.Where(c =>
 
823
         {
 
824
           ParameterInfo[] parameters = c.GetParameters();
 
825
           if (parameters.Length != args.Length)
 
826
             return false;
 
827
 
 
828
           for (int i = 0; i < parameters.Length; i++)
 
829
           {
 
830
             ParameterInfo parameter = parameters[i];
 
831
             object value = args[i];
 
832
 
 
833
             if (!IsCompatibleValue(value, parameter.ParameterType))
 
834
               return false;
 
835
           }
 
836
 
 
837
           return true;
 
838
         }).FirstOrDefault();
 
839
 
 
840
       if (match == null)
 
841
         throw new Exception("Could not create '{0}' with given parameters.".FormatWith(CultureInfo.InvariantCulture, type));
 
842
 
 
843
       return match.Invoke(args);
 
844
#endif
 
845
     }
 
846
 
 
847
    public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName)
 
848
    {
 
849
      int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
 
850
 
 
851
      if (assemblyDelimiterIndex != null)
 
852
      {
 
853
        typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim();
 
854
        assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim();
 
855
      }
 
856
      else
 
857
      {
 
858
        typeName = fullyQualifiedTypeName;
 
859
        assemblyName = null;
 
860
      }
 
861
 
 
862
    }
 
863
 
 
864
    private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
 
865
    {
 
866
      // we need to get the first comma following all surrounded in brackets because of generic types
 
867
      // 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
 
868
      int scope = 0;
 
869
      for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
 
870
      {
 
871
        char current = fullyQualifiedTypeName[i];
 
872
        switch (current)
 
873
        {
 
874
          case '[':
 
875
            scope++;
 
876
            break;
 
877
          case ']':
 
878
            scope--;
 
879
            break;
 
880
          case ',':
 
881
            if (scope == 0)
 
882
              return i;
 
883
            break;
 
884
        }
 
885
      }
 
886
 
 
887
      return null;
 
888
    }
 
889
 
 
890
    public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo)
 
891
    {
 
892
      const BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
 
893
 
 
894
      switch (memberInfo.MemberType())
 
895
      {
 
896
        case MemberTypes.Property:
 
897
          PropertyInfo propertyInfo = (PropertyInfo) memberInfo;
 
898
 
 
899
          Type[] types = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray();
 
900
 
 
901
          return targetType.GetProperty(propertyInfo.Name, bindingAttr, null, propertyInfo.PropertyType, types, null);
 
902
        default:
 
903
          return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), bindingAttr).SingleOrDefault();
 
904
      }
 
905
    }
 
906
 
 
907
    public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
 
908
    {
 
909
      ValidationUtils.ArgumentNotNull(targetType, "targetType");
 
910
 
 
911
      List<MemberInfo> fieldInfos = new List<MemberInfo>(targetType.GetFields(bindingAttr));
 
912
#if !NETFX_CORE
 
913
      // Type.GetFields doesn't return inherited private fields
 
914
      // manually find private fields from base class
 
915
      GetChildPrivateFields(fieldInfos, targetType, bindingAttr);
 
916
#endif
 
917
 
 
918
      return fieldInfos.Cast<FieldInfo>();
 
919
    }
 
920
 
 
921
    private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
 
922
    {
 
923
      // fix weirdness with private FieldInfos only being returned for the current Type
 
924
      // find base type fields and add them to result
 
925
      if ((bindingAttr & BindingFlags.NonPublic) != 0)
 
926
      {
 
927
        // modify flags to not search for public fields
 
928
        BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
 
929
 
 
930
        while ((targetType = targetType.BaseType()) != null)
 
931
        {
 
932
          // filter out protected fields
 
933
          IEnumerable<MemberInfo> childPrivateFields =
 
934
            targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate).Cast<MemberInfo>();
 
935
 
 
936
          initialFields.AddRange(childPrivateFields);
 
937
        }
 
938
      }
 
939
    }
 
940
 
 
941
    public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
 
942
    {
 
943
      ValidationUtils.ArgumentNotNull(targetType, "targetType");
 
944
 
 
945
      List<PropertyInfo> propertyInfos = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
 
946
      GetChildPrivateProperties(propertyInfos, targetType, bindingAttr);
 
947
 
 
948
      // a base class private getter/setter will be inaccessable unless the property was gotten from the base class
 
949
      for (int i = 0; i < propertyInfos.Count; i++)
 
950
      {
 
951
        PropertyInfo member = propertyInfos[i];
 
952
        if (member.DeclaringType != targetType)
 
953
        {
 
954
          PropertyInfo declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType, member);
 
955
          propertyInfos[i] = declaredMember;
 
956
        }
 
957
      }
 
958
 
 
959
      return propertyInfos;
 
960
    }
 
961
 
 
962
    public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
 
963
    {
 
964
      return ((bindingAttr & flag) == flag)
 
965
        ? bindingAttr ^ flag
 
966
        : bindingAttr;
 
967
    }
 
968
 
 
969
    private static void GetChildPrivateProperties(IList<PropertyInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
 
970
    {
 
971
      // fix weirdness with private PropertyInfos only being returned for the current Type
 
972
      // find base type properties and add them to result
 
973
      if ((bindingAttr & BindingFlags.NonPublic) != 0)
 
974
      {
 
975
        // modify flags to not search for public fields
 
976
        BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
 
977
 
 
978
        while ((targetType = targetType.BaseType()) != null)
 
979
        {
 
980
          foreach (PropertyInfo propertyInfo in targetType.GetProperties(nonPublicBindingAttr))
 
981
          {
 
982
            PropertyInfo nonPublicProperty = propertyInfo;
 
983
 
 
984
            // have to test on name rather than reference because instances are different
 
985
            // depending on the type that GetProperties was called on
 
986
            int index = initialProperties.IndexOf(p => p.Name == nonPublicProperty.Name);
 
987
            if (index == -1)
 
988
            {
 
989
              initialProperties.Add(nonPublicProperty);
 
990
            }
 
991
            else
 
992
            {
 
993
              // replace nonpublic properties for a child, but gotten from
 
994
              // the parent with the one from the child
 
995
              // the property gotten from the child will have access to private getter/setter
 
996
              initialProperties[index] = nonPublicProperty;
 
997
            }
 
998
          }
 
999
        }
 
1000
      }
 
1001
    }
 
1002
 
 
1003
    public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method)
 
1004
    {
 
1005
      bool isMethodOverriden = currentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
 
1006
        .Any(info =>
 
1007
             info.Name == method &&
 
1008
             // check that the method overrides the original on DynamicObjectProxy
 
1009
             info.DeclaringType != methodDeclaringType
 
1010
             // todo - find out whether there is a way to do this in winrt
 
1011
#if !NETFX_CORE
 
1012
             && info.GetBaseDefinition().DeclaringType == methodDeclaringType
 
1013
#endif
 
1014
        );
 
1015
 
 
1016
      return isMethodOverriden;
 
1017
    }
 
1018
 
 
1019
    public static object GetDefaultValue(Type type)
 
1020
    {
 
1021
      if (!type.IsValueType())
 
1022
        return null;
 
1023
 
 
1024
      switch (ConvertUtils.GetTypeCode(type))
 
1025
      {
 
1026
        case TypeCode.Boolean:
 
1027
          return false;
 
1028
        case TypeCode.Char:
 
1029
        case TypeCode.SByte:
 
1030
        case TypeCode.Byte:
 
1031
        case TypeCode.Int16:
 
1032
        case TypeCode.UInt16:
 
1033
        case TypeCode.Int32:
 
1034
        case TypeCode.UInt32:
 
1035
          return 0;
 
1036
        case TypeCode.Int64:
 
1037
        case TypeCode.UInt64:
 
1038
          return 0L;
 
1039
        case TypeCode.Single:
 
1040
          return 0f;
 
1041
        case TypeCode.Double:
 
1042
          return 0.0;
 
1043
        case TypeCode.Decimal:
 
1044
          return 0m;
 
1045
        case TypeCode.DateTime:
 
1046
          return new DateTime();
 
1047
      }
 
1048
 
 
1049
      if (type == typeof(Guid))
 
1050
        return new Guid();
 
1051
 
 
1052
#if !NET20
 
1053
      if (type == typeof(DateTimeOffset))
 
1054
        return new DateTimeOffset();
 
1055
#endif
 
1056
 
 
1057
      if (IsNullable(type))
 
1058
        return null;
 
1059
 
 
1060
      // possibly use IL initobj for perf here?
 
1061
      return Activator.CreateInstance(type);
 
1062
    }
 
1063
  }
 
1064
}
 
 
b'\\ No newline at end of file'