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
Symbol Coverage Trend
View:
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 |
} |