Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Serialization\JsonTypeReflector.cs

Symbol Coverage: 93.18% (82 of 88)

Branch Coverage: 100.00% (44 of 44)

Cyclomatic Complexity Avg: 2.06 Max:4

Code Lines: 94


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.ComponentModel;
28
using System.Globalization;
29
using System.Linq;
30
using System.Reflection;
31
using System.Runtime.Serialization;
32
using System.Security.Permissions;
33
using Newtonsoft.Json.Utilities;
34

  
35
namespace Newtonsoft.Json.Serialization
36
{
37
#if !SILVERLIGHT && !PocketPC && !NET20
38
  internal interface IMetadataTypeAttribute
39
  {
40
    Type MetadataClassType { get; }
41
  }
42
#endif
43

  
44
  internal static class JsonTypeReflector
45
  {
46
    public const string IdPropertyName = "$id";
47
    public const string RefPropertyName = "$ref";
48
    public const string TypePropertyName = "$type";
49
    public const string ArrayValuesPropertyName = "$values";
50

  
51
    public const string ShouldSerializePrefix = "ShouldSerialize";
52

  
53
 1
    private static readonly ThreadSafeStore<ICustomAttributeProvider, Type> JsonConverterTypeCache = new ThreadSafeStore<ICustomAttributeProvider, Type>(GetJsonConverterTypeFromAttribute);
54
#if !SILVERLIGHT && !PocketPC && !NET20
55
 1
    private static readonly ThreadSafeStore<Type, Type> AssociatedMetadataTypesCache = new ThreadSafeStore<Type, Type>(GetAssociateMetadataTypeFromAttribute);
56

  
57
    private const string MetadataTypeAttributeTypeName =
58
      "System.ComponentModel.DataAnnotations.MetadataTypeAttribute, System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
59
    private static Type _cachedMetadataTypeAttributeType;
60
#endif
61
#if SILVERLIGHT
62
    private static readonly ThreadSafeStore<ICustomAttributeProvider, Type> TypeConverterTypeCache = new ThreadSafeStore<ICustomAttributeProvider, Type>(GetTypeConverterTypeFromAttribute);
63

  
64
    private static Type GetTypeConverterTypeFromAttribute(ICustomAttributeProvider attributeProvider)
65
    {
66
      TypeConverterAttribute converterAttribute = GetAttribute<TypeConverterAttribute>(attributeProvider);
67
      if (converterAttribute == null)
68
        return null;
69

  
70
      return Type.GetType(converterAttribute.ConverterTypeName);
71
    }
72

  
73
    private static Type GetTypeConverterType(ICustomAttributeProvider attributeProvider)
74
    {
75
      return TypeConverterTypeCache.Get(attributeProvider);
76
    }
77
#endif
78

  
79
    public static JsonContainerAttribute GetJsonContainerAttribute(Type type)
80
    {
81
 2168
      return CachedAttributeGetter<JsonContainerAttribute>.GetAttribute(type);
82
 2168
    }
83

  
84
    public static JsonObjectAttribute GetJsonObjectAttribute(Type type)
85
    {
86
 437
      return GetJsonContainerAttribute(type) as JsonObjectAttribute;
87
 437
    }
88

  
89
    public static JsonArrayAttribute GetJsonArrayAttribute(Type type)
90
    {
91
 251
      return GetJsonContainerAttribute(type) as JsonArrayAttribute;
92
 251
    }
93

  
94
#if !PocketPC && !NET20
95
    public static DataContractAttribute GetDataContractAttribute(Type type)
96
    {
97
 1228
      return CachedAttributeGetter<DataContractAttribute>.GetAttribute(type);
98
 1228
    }
99
#endif
100

  
101
    public static MemberSerialization GetObjectMemberSerialization(Type objectType)
102
    {
103
 173
      JsonObjectAttribute objectAttribute = GetJsonObjectAttribute(objectType);
104

  
105
 173
      if (objectAttribute == null)
106
      {
107
#if !PocketPC && !NET20
108
 160
        DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType);
109

  
110
 160
        if (dataContractAttribute != null)
111
 10
          return MemberSerialization.OptIn;
112
#endif
113

  
114
 150
        return MemberSerialization.OptOut;
115
      }
116

  
117
 13
      return objectAttribute.MemberSerialization;
118
 173
    }
119

  
120
    private static Type GetJsonConverterType(ICustomAttributeProvider attributeProvider)
121
    {
122
 1506
      return JsonConverterTypeCache.Get(attributeProvider);
123
 1506
    }
124

  
125
    private static Type GetJsonConverterTypeFromAttribute(ICustomAttributeProvider attributeProvider)
126
    {
127
 863
      JsonConverterAttribute converterAttribute = GetAttribute<JsonConverterAttribute>(attributeProvider);
128
 863
      return (converterAttribute != null)
129
 863
        ? converterAttribute.ConverterType
130
 863
        : null;
131
 863
    }
132

  
133
    public static JsonConverter GetJsonConverter(ICustomAttributeProvider attributeProvider, Type targetConvertedType)
134
    {
135
 1506
      Type converterType = GetJsonConverterType(attributeProvider);
136

  
137
 1506
      if (converterType != null)
138
      {
139
 13
        JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
140

  
141
 13
        if (!memberConverter.CanConvert(targetConvertedType))
142
 1
          throw new JsonSerializationException("JsonConverter {0} on {1} is not compatible with member type {2}.".FormatWith(CultureInfo.InvariantCulture, memberConverter.GetType().Name, attributeProvider, targetConvertedType.Name));
143

  
144
 12
        return memberConverter;
145
      }
146

  
147
 1493
      return null;
148
 1505
    }
149

  
150
#if !PocketPC
151
    public static TypeConverter GetTypeConverter(Type type)
152
    {
153
#if !SILVERLIGHT
154
 218
      return TypeDescriptor.GetConverter(type);
155
#else
156
      Type converterType = GetTypeConverterType(type);
157

  
158
      if (converterType != null)
159
        return (TypeConverter)ReflectionUtils.CreateInstance(converterType);
160

  
161
      return null;
162
#endif
163
 218
    }
164
#endif
165

  
166
#if !SILVERLIGHT && !PocketPC && !NET20
167
    private static Type GetAssociatedMetadataType(Type type)
168
    {
169
 3927
      return AssociatedMetadataTypesCache.Get(type);
170
 3927
    }
171

  
172
    private static Type GetAssociateMetadataTypeFromAttribute(Type type)
173
    {
174
 304
      Type metadataTypeAttributeType = GetMetadataTypeAttributeType();
175
 304
      if (metadataTypeAttributeType == null)
176
 0
        return null;
177

  
178
 304
      object attribute = type.GetCustomAttributes(metadataTypeAttributeType, true).SingleOrDefault();
179
 304
      if (attribute == null)
180
 300
        return null;
181

  
182
 4
      IMetadataTypeAttribute metadataTypeAttribute = (DynamicCodeGeneration)
183
 4
                                                       ? DynamicWrapper.CreateWrapper<IMetadataTypeAttribute>(attribute)
184
 4
                                                       : new LateBoundMetadataTypeAttribute(attribute);
185

  
186
 4
      return metadataTypeAttribute.MetadataClassType;
187
 304
    }
188

  
189
    private static Type GetMetadataTypeAttributeType()
190
    {
191
      // always attempt to get the metadata type attribute type
192
      // the assembly may have been loaded since last time
193
 304
      if (_cachedMetadataTypeAttributeType == null)
194
      {
195
 1
        Type metadataTypeAttributeType = Type.GetType(MetadataTypeAttributeTypeName);
196

  
197
 1
        if (metadataTypeAttributeType != null)
198
 1
          _cachedMetadataTypeAttributeType = metadataTypeAttributeType;
199
        else
200
 0
          return null;
201
      }
202
      
203
 304
      return _cachedMetadataTypeAttributeType;
204
 304
    }
205

  
206
    private static T GetAttribute<T>(Type type) where T : Attribute
207
    {
208
 887
      Type metadataType = GetAssociatedMetadataType(type);
209
 887
      if (metadataType != null)
210
      {
211
 13
        T attribute = ReflectionUtils.GetAttribute<T>(metadataType, true);
212
 13
        if (attribute != null)
213
 2
          return attribute;
214
      }
215

  
216
 885
      return ReflectionUtils.GetAttribute<T>(type, true);
217
 887
    }
218

  
219
    private static T GetAttribute<T>(MemberInfo memberInfo) where T : Attribute
220
    {
221
 3040
      Type metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType);
222
 3040
      if (metadataType != null)
223
      {
224
 91
        MemberInfo metadataTypeMemberInfo = metadataType.GetMember(memberInfo.Name,
225
 91
          memberInfo.MemberType,
226
 91
          BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance).SingleOrDefault();
227

  
228
 91
        if (metadataTypeMemberInfo != null)
229
        {
230
 28
          T attribute = ReflectionUtils.GetAttribute<T>(metadataTypeMemberInfo, true);
231
 28
          if (attribute != null)
232
 5
            return attribute;
233
        }
234
      }
235

  
236
 3035
      return ReflectionUtils.GetAttribute<T>(memberInfo, true);
237
 3040
    }
238

  
239
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
240
    {
241
 3927
      Type type = attributeProvider as Type;
242
 3927
      if (type != null)
243
 887
        return GetAttribute<T>(type);
244

  
245
 3040
      MemberInfo memberInfo = attributeProvider as MemberInfo;
246
 3040
      if (memberInfo != null)
247
 3040
        return GetAttribute<T>(memberInfo);
248

  
249
 0
      return ReflectionUtils.GetAttribute<T>(attributeProvider, true);
250
 3927
    }
251
#else
252
    public static T GetAttribute<T>(ICustomAttributeProvider attributeProvider) where T : Attribute
253
    {
254
      return ReflectionUtils.GetAttribute<T>(attributeProvider, true);
255
    }
256
#endif
257

  
258
    private static bool? _dynamicCodeGeneration;
259

  
260
    public static bool DynamicCodeGeneration
261
    {
262
      get
263
      {
264
 869
        if (_dynamicCodeGeneration == null)
265
        {
266
#if !PocketPC && !SILVERLIGHT
267
          try
268
          {
269
 1
            new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
270
 1
            new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess).Demand();
271
 1
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
272
 1
            _dynamicCodeGeneration = true;
273
          }
274
 0
          catch (Exception)
275
          {
276
 0
            _dynamicCodeGeneration = false;
277
          }
278
#else
279
          _dynamicCodeGeneration = false;
280
#endif
281
        }
282

  
283
 869
        return _dynamicCodeGeneration.Value;
284
 869
      }
285
    }
286

  
287
    public static ReflectionDelegateFactory ReflectionDelegateFactory
288
    {
289
      get
290
      {
291
#if !PocketPC && !SILVERLIGHT
292
 267
        if (DynamicCodeGeneration)
293
 267
          return DynamicReflectionDelegateFactory.Instance;
294
#endif
295

  
296
 0
        return LateBoundReflectionDelegateFactory.Instance;
297
 267
      }
298
    }
299
  }
300
}