diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs index 20a127f4..b8b9269b 100644 --- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs @@ -75,4 +75,4 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.3.17415")] +[assembly: AssemblyFileVersion("6.0.3.17420")] diff --git a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs index 83c9ec44..2e34257b 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/JsonSerializerTest.cs @@ -2438,7 +2438,7 @@ keyword such as type of business."" Assert.AreEqual("titleId", n.FidOrder[n.FidOrder.Count - 1]); } -#if !(NET20 || NETFX_CORE || PORTABLE || PORTABLE40) +#if !(NET20 || NETFX_CORE) [MetadataType(typeof(OptInClassMetadata))] public class OptInClass { @@ -7877,6 +7877,41 @@ Parameter name: value", Assert.AreEqual(dt, (DateTimeOffset)v.Value); } #endif + + [Test] + public void DeserializeInvalidOctalRootError() + { + ExceptionAssert.Throws( + "Input string '020474068' is not a valid number. Path '', line 1, position 9.", + () => JsonConvert.DeserializeObject("020474068")); + } + + [Test] + public void DeserializedDerivedWithPrivate() + { + string json = @"{ + ""DerivedProperty"": ""derived"", + ""BaseProperty"": ""base"" +}"; + + var d = JsonConvert.DeserializeObject(json); + + Assert.AreEqual("base", d.BaseProperty); + Assert.AreEqual("derived", d.DerivedProperty); + } + } + + public class DerivedWithPrivate : BaseWithPrivate + { + [JsonProperty] + public string DerivedProperty { get; private set; } + } + + + public class BaseWithPrivate + { + [JsonProperty] + public string BaseProperty { get; private set; } } public abstract class Test diff --git a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs index 387b129f..6c2284db 100644 --- a/Src/Newtonsoft.Json/Converters/BinaryConverter.cs +++ b/Src/Newtonsoft.Json/Converters/BinaryConverter.cs @@ -32,13 +32,6 @@ using System.Collections.Generic; namespace Newtonsoft.Json.Converters { -#if !NET20 - internal interface IBinary - { - byte[] ToArray(); - } -#endif - /// /// Converts a binary value to and from a base 64 string value. /// @@ -46,6 +39,8 @@ namespace Newtonsoft.Json.Converters { #if !NET20 private const string BinaryTypeName = "System.Data.Linq.Binary"; + private const string BinaryToArrayName = "ToArray"; + private ReflectionObject _reflectionObject; #endif /// @@ -72,8 +67,8 @@ namespace Newtonsoft.Json.Converters #if !(NET20) if (value.GetType().AssignableToTypeName(BinaryTypeName)) { - IBinary binary = DynamicWrapper.CreateWrapper(value); - return binary.ToArray(); + EnsureReflectionObject(value.GetType()); + return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName); } #endif if (value is SqlBinary) @@ -82,6 +77,14 @@ namespace Newtonsoft.Json.Converters throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } +#if !NET20 + private void EnsureReflectionObject(Type t) + { + if (_reflectionObject == null) + _reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new[] { typeof(byte[]) }), BinaryToArrayName); + } +#endif + /// /// Reads the JSON representation of the object. /// @@ -122,10 +125,13 @@ namespace Newtonsoft.Json.Converters throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - #if !NET20 if (t.AssignableToTypeName(BinaryTypeName)) - return Activator.CreateInstance(t, data); + { + EnsureReflectionObject(t); + + return _reflectionObject.Creator(data); + } #endif if (t == typeof(SqlBinary)) @@ -179,5 +185,4 @@ namespace Newtonsoft.Json.Converters } } } - #endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs b/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs index e7ad4f64..d3b10751 100644 --- a/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs +++ b/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs @@ -31,12 +31,6 @@ using Newtonsoft.Json.Utilities; namespace Newtonsoft.Json.Converters { - internal interface IEntityKeyMember - { - string Key { get; set; } - object Value { get; set; } - } - /// /// Converts an Entity Framework EntityKey to and from JSON. /// @@ -48,6 +42,8 @@ namespace Newtonsoft.Json.Converters private const string TypePropertyName = "Type"; private const string ValuePropertyName = "Value"; + private static ReflectionObject _reflectionObject; + /// /// Writes the JSON representation of the object. /// @@ -56,26 +52,30 @@ namespace Newtonsoft.Json.Converters /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { + EnsureReflectionObject(value.GetType()); + DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; - IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper(value); - Type keyType = (entityKeyMember.Value != null) ? entityKeyMember.Value.GetType() : null; + string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName); + object keyValue = _reflectionObject.GetValue(value, ValuePropertyName); + + Type keyValueType = (keyValue != null) ? keyValue.GetType() : null; writer.WriteStartObject(); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName); - writer.WriteValue(entityKeyMember.Key); + writer.WriteValue(keyName); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(TypePropertyName) : TypePropertyName); - writer.WriteValue((keyType != null) ? keyType.FullName : null); + writer.WriteValue((keyValueType != null) ? keyValueType.FullName : null); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValuePropertyName) : ValuePropertyName); - if (keyType != null) + if (keyValueType != null) { string valueJson; - if (JsonSerializerInternalWriter.TryConvertToString(entityKeyMember.Value, keyType, out valueJson)) + if (JsonSerializerInternalWriter.TryConvertToString(keyValue, keyValueType, out valueJson)) writer.WriteValue(valueJson); else - writer.WriteValue(entityKeyMember.Value); + writer.WriteValue(keyValue); } else { @@ -109,11 +109,13 @@ namespace Newtonsoft.Json.Converters /// The object value. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper(Activator.CreateInstance(objectType)); + EnsureReflectionObject(objectType); + + object entityKeyMember = _reflectionObject.Creator(); ReadAndAssertProperty(reader, KeyPropertyName); ReadAndAssert(reader); - entityKeyMember.Key = reader.Value.ToString(); + _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value.ToString()); ReadAndAssertProperty(reader, TypePropertyName); ReadAndAssert(reader); @@ -123,11 +125,17 @@ namespace Newtonsoft.Json.Converters ReadAndAssertProperty(reader, ValuePropertyName); ReadAndAssert(reader); - entityKeyMember.Value = serializer.Deserialize(reader, t); + _reflectionObject.SetValue(entityKeyMember, ValuePropertyName, serializer.Deserialize(reader, t)); ReadAndAssert(reader); - return DynamicWrapper.GetUnderlyingObject(entityKeyMember); + return entityKeyMember; + } + + private static void EnsureReflectionObject(Type objectType) + { + if (_reflectionObject == null) + _reflectionObject = ReflectionObject.Create(objectType, KeyPropertyName, ValuePropertyName); } /// diff --git a/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs b/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs index fa0b157c..4120d1d7 100644 --- a/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs +++ b/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs @@ -39,6 +39,17 @@ namespace Newtonsoft.Json.Converters private const string KeyName = "Key"; private const string ValueName = "Value"; + private static readonly ThreadSafeStore ReflectionObjectPerType = new ThreadSafeStore(InitializeReflectionObject); + + private static ReflectionObject InitializeReflectionObject(Type t) + { + IList genericArguments = t.GetGenericArguments(); + Type keyType = genericArguments[0]; + Type valueType = genericArguments[1]; + + return ReflectionObject.Create(t, t.GetConstructor(new[] { keyType, valueType }), KeyName, ValueName); + } + /// /// Writes the JSON representation of the object. /// @@ -47,22 +58,15 @@ namespace Newtonsoft.Json.Converters /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - Type t = value.GetType(); - IList genericArguments = t.GetGenericArguments(); - Type keyType = genericArguments[0]; - Type valueType = genericArguments[1]; - - PropertyInfo keyProperty = t.GetProperty(KeyName); - PropertyInfo valueProperty = t.GetProperty(ValueName); + ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType()); DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); - writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName); - serializer.Serialize(writer, ReflectionUtils.GetMemberValue(keyProperty, value), keyType); + serializer.Serialize(writer, reflectionObject.GetValue(value, KeyName), reflectionObject.GetType(KeyName)); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValueName) : ValueName); - serializer.Serialize(writer, ReflectionUtils.GetMemberValue(valueProperty, value), valueType); + serializer.Serialize(writer, reflectionObject.GetValue(value, ValueName), reflectionObject.GetType(ValueName)); writer.WriteEndObject(); } @@ -78,6 +82,12 @@ namespace Newtonsoft.Json.Converters { bool isNullable = ReflectionUtils.IsNullableType(objectType); + Type t = (isNullable) + ? Nullable.GetUnderlyingType(objectType) + : objectType; + + ReflectionObject reflectionObject = ReflectionObjectPerType.Get(t); + if (reader.TokenType == JsonToken.Null) { if (!isNullable) @@ -86,14 +96,6 @@ namespace Newtonsoft.Json.Converters return null; } - Type t = (isNullable) - ? Nullable.GetUnderlyingType(objectType) - : objectType; - - IList genericArguments = t.GetGenericArguments(); - Type keyType = genericArguments[0]; - Type valueType = genericArguments[1]; - object key = null; object value = null; @@ -105,12 +107,12 @@ namespace Newtonsoft.Json.Converters if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase)) { reader.Read(); - key = serializer.Deserialize(reader, keyType); + key = serializer.Deserialize(reader, reflectionObject.GetType(KeyName)); } else if (string.Equals(propertyName, ValueName, StringComparison.OrdinalIgnoreCase)) { reader.Read(); - value = serializer.Deserialize(reader, valueType); + value = serializer.Deserialize(reader, reflectionObject.GetType(ValueName)); } else { @@ -120,7 +122,7 @@ namespace Newtonsoft.Json.Converters reader.Read(); } - return Activator.CreateInstance(t, key, value); + return reflectionObject.Creator(key, value); } /// diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs index c7691f00..d322b033 100644 --- a/Src/Newtonsoft.Json/Linq/JToken.cs +++ b/Src/Newtonsoft.Json/Linq/JToken.cs @@ -69,7 +69,9 @@ namespace Newtonsoft.Json.Linq private static readonly JTokenType[] BooleanTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] NumberTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; +#if !(NET20 || NET35 || PORTABLE40 || PORTABLE) private static readonly JTokenType[] BigIntegerTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes }; +#endif private static readonly JTokenType[] StringTypes = new[] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri }; private static readonly JTokenType[] GuidTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes }; private static readonly JTokenType[] TimeSpanTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan }; diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj index 8e8b2c24..d569991f 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj @@ -224,17 +224,16 @@ - - + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj index 0626400d..137c46b1 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj @@ -231,13 +231,11 @@ - - @@ -248,6 +246,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj index b32797fb..7b0722f4 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj @@ -231,13 +231,11 @@ - - @@ -248,6 +246,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj index 75d4ffac..dddd7c2b 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj @@ -186,7 +186,6 @@ - @@ -209,7 +208,6 @@ - @@ -223,6 +221,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj index da27e4b4..ffe7a0d2 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj @@ -191,7 +191,6 @@ - @@ -213,7 +212,6 @@ - @@ -227,6 +225,7 @@ + diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj index db947fa0..1d0cdfb1 100644 --- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj +++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj @@ -190,7 +190,6 @@ - @@ -212,7 +211,7 @@ - + diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs index 0c71142c..f22b3357 100644 --- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs +++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs @@ -91,5 +91,5 @@ using System.Security; // by using the '*' as shown below: [assembly: AssemblyVersion("6.0.0.0")] -[assembly: AssemblyFileVersion("6.0.3.17415")] +[assembly: AssemblyFileVersion("6.0.3.17420")] [assembly: CLSCompliant(true)] diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 7135e6b3..6cb642b6 100644 --- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -41,13 +41,6 @@ using System.Runtime.Serialization; namespace Newtonsoft.Json.Serialization { -#if !NET20 && !NETFX_CORE - internal interface IMetadataTypeAttribute - { - Type MetadataClassType { get; } - } -#endif - internal static class JsonTypeReflector { private static bool? _dynamicCodeGeneration; @@ -63,7 +56,7 @@ namespace Newtonsoft.Json.Serialization public const string SpecifiedPostfix = "Specified"; private static readonly ThreadSafeStore JsonConverterTypeCache = new ThreadSafeStore(GetJsonConverterTypeFromAttribute); -#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE) +#if !(NET20 || NETFX_CORE) private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); private const string MetadataTypeAttributeTypeName = @@ -208,27 +201,30 @@ namespace Newtonsoft.Json.Serialization } #endif -#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE) +#if !(NET20 || NETFX_CORE) private static Type GetAssociatedMetadataType(Type type) { return AssociatedMetadataTypesCache.Get(type); } + private static ReflectionObject _metadataTypeAttributeReflectionObject; + private static Type GetAssociateMetadataTypeFromAttribute(Type type) { Type metadataTypeAttributeType = GetMetadataTypeAttributeType(); if (metadataTypeAttributeType == null) return null; - object attribute = type.GetCustomAttributes(metadataTypeAttributeType, true).SingleOrDefault(); + Attribute attribute = ReflectionUtils.GetAttributes(type, metadataTypeAttributeType, true).SingleOrDefault(); if (attribute == null) return null; - IMetadataTypeAttribute metadataTypeAttribute = (DynamicCodeGeneration) - ? DynamicWrapper.CreateWrapper(attribute) - : new LateBoundMetadataTypeAttribute(attribute); + const string metadataClassTypeName = "MetadataClassType"; - return metadataTypeAttribute.MetadataClassType; + if (_metadataTypeAttributeReflectionObject == null) + _metadataTypeAttributeReflectionObject = ReflectionObject.Create(metadataTypeAttributeType, metadataClassTypeName); + + return (Type)_metadataTypeAttributeReflectionObject.GetValue(attribute, metadataClassTypeName); } private static Type GetMetadataTypeAttributeType() @@ -253,7 +249,7 @@ namespace Newtonsoft.Json.Serialization { T attribute; -#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE) +#if !(NET20 || NETFX_CORE) Type metadataType = GetAssociatedMetadataType(type); if (metadataType != null) { @@ -281,7 +277,7 @@ namespace Newtonsoft.Json.Serialization { T attribute; -#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE) +#if !(NET20 || NETFX_CORE) Type metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); if (metadataType != null) { @@ -388,15 +384,15 @@ namespace Newtonsoft.Json.Serialization _fullyTrusted = appDomain.IsHomogenous && appDomain.IsFullyTrusted; #else - try - { - new SecurityPermission(PermissionState.Unrestricted).Demand(); - _fullyTrusted = true; - } - catch (Exception) - { - _fullyTrusted = false; - } + try + { + new SecurityPermission(PermissionState.Unrestricted).Demand(); + _fullyTrusted = true; + } + catch (Exception) + { + _fullyTrusted = false; + } #endif } @@ -414,7 +410,7 @@ namespace Newtonsoft.Json.Serialization return LateBoundReflectionDelegateFactory.Instance; #elif !(PORTABLE40) - return ExpressionReflectionDelegateFactory.Instance; + return ExpressionReflectionDelegateFactory.Instance; #else return LateBoundReflectionDelegateFactory.Instance; #endif diff --git a/Src/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs b/Src/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs deleted file mode 100644 index 4583443e..00000000 --- a/Src/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs +++ /dev/null @@ -1,60 +0,0 @@ -#region License -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -#endregion - -#if !NET20 && !NETFX_CORE -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Newtonsoft.Json.Utilities; -using System.Reflection; - -namespace Newtonsoft.Json.Serialization -{ - internal class LateBoundMetadataTypeAttribute : IMetadataTypeAttribute - { - private static PropertyInfo _metadataClassTypeProperty; - - private readonly object _attribute; - - public LateBoundMetadataTypeAttribute(object attribute) - { - _attribute = attribute; - } - - public Type MetadataClassType - { - get - { - if (_metadataClassTypeProperty == null) - _metadataClassTypeProperty = _attribute.GetType().GetProperty("MetadataClassType"); - - return (Type)ReflectionUtils.GetMemberValue(_metadataClassTypeProperty, _attribute); - } - } - } -} - -#endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs index 1316e248..3bedfc56 100644 --- a/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -160,6 +160,7 @@ namespace Newtonsoft.Json.Utilities #endif }; +#if !(NETFX_CORE || PORTABLE) private static readonly List PrimitiveTypeCodes = new List { new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, @@ -182,6 +183,7 @@ namespace Newtonsoft.Json.Utilities new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, // no 17 in TypeCode for some reason new TypeInformation { Type = typeof(string), TypeCode = PrimitiveTypeCode.String } }; +#endif public static PrimitiveTypeCode GetTypeCode(Type t) { diff --git a/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs b/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs deleted file mode 100644 index aa256c3a..00000000 --- a/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs +++ /dev/null @@ -1,266 +0,0 @@ -#region License -// Copyright (c) 2007 James Newton-King -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -#endregion - -#if !(NETFX_CORE || PORTABLE40 || PORTABLE) -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Reflection.Emit; -using System.Resources; -using System.Globalization; -#if NET20 -using Newtonsoft.Json.Utilities.LinqBridge; -#else -using System.Linq; - -#endif - -namespace Newtonsoft.Json.Utilities -{ - internal class DynamicWrapperBase - { - protected internal object UnderlyingObject; - } - - internal static class DynamicWrapper - { - private static readonly object _lock = new object(); - private static readonly WrapperDictionary _wrapperDictionary = new WrapperDictionary(); - - private static ModuleBuilder _moduleBuilder; - - private static ModuleBuilder ModuleBuilder - { - get - { - Init(); - return _moduleBuilder; - } - } - - private static void Init() - { - if (_moduleBuilder == null) - { - lock (_lock) - { - if (_moduleBuilder == null) - { - AssemblyName assemblyName = new AssemblyName("Newtonsoft.Json.Dynamic"); - assemblyName.KeyPair = new StrongNameKeyPair(GetStrongKey()); - - AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); - _moduleBuilder = assembly.DefineDynamicModule("Newtonsoft.Json.DynamicModule", false); - } - } - } - } - - private static byte[] GetStrongKey() - { - const string name = "Newtonsoft.Json.Dynamic.snk"; - - using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name)) - { - if (stream == null) - throw new MissingManifestResourceException("Should have " + name + " as an embedded resource."); - - int length = (int)stream.Length; - byte[] buffer = new byte[length]; - stream.Read(buffer, 0, length); - - return buffer; - } - } - - public static Type GetWrapper(Type interfaceType, Type realObjectType) - { - Type wrapperType = _wrapperDictionary.GetType(interfaceType, realObjectType); - - if (wrapperType == null) - { - lock (_lock) - { - wrapperType = _wrapperDictionary.GetType(interfaceType, realObjectType); - - if (wrapperType == null) - { - wrapperType = GenerateWrapperType(interfaceType, realObjectType); - _wrapperDictionary.SetType(interfaceType, realObjectType, wrapperType); - } - } - } - - return wrapperType; - } - - public static object GetUnderlyingObject(object wrapper) - { - DynamicWrapperBase wrapperBase = wrapper as DynamicWrapperBase; - if (wrapperBase == null) - throw new ArgumentException("Object is not a wrapper.", "wrapper"); - - return wrapperBase.UnderlyingObject; - } - - private static Type GenerateWrapperType(Type interfaceType, Type underlyingType) - { - TypeBuilder wrapperBuilder = ModuleBuilder.DefineType( - "{0}_{1}_Wrapper".FormatWith(CultureInfo.InvariantCulture, interfaceType.Name, underlyingType.Name), - TypeAttributes.NotPublic | TypeAttributes.Sealed, - typeof(DynamicWrapperBase), - new[] { interfaceType }); - - WrapperMethodBuilder wrapperMethod = new WrapperMethodBuilder(underlyingType, wrapperBuilder); - - foreach (MethodInfo method in interfaceType.GetAllMethods()) - { - wrapperMethod.Generate(method); - } - - return wrapperBuilder.CreateType(); - } - - public static T CreateWrapper(object realObject) where T : class - { - var dynamicType = GetWrapper(typeof(T), realObject.GetType()); - var dynamicWrapper = (DynamicWrapperBase)Activator.CreateInstance(dynamicType); - - dynamicWrapper.UnderlyingObject = realObject; - - return dynamicWrapper as T; - } - } - - internal class WrapperMethodBuilder - { - private readonly Type _realObjectType; - private readonly TypeBuilder _wrapperBuilder; - - public WrapperMethodBuilder(Type realObjectType, TypeBuilder proxyBuilder) - { - _realObjectType = realObjectType; - _wrapperBuilder = proxyBuilder; - } - - public void Generate(MethodInfo newMethod) - { - if (newMethod.IsGenericMethod) - newMethod = newMethod.GetGenericMethodDefinition(); - - FieldInfo srcField = typeof(DynamicWrapperBase).GetField("UnderlyingObject", BindingFlags.Instance | BindingFlags.NonPublic); - - var parameters = newMethod.GetParameters(); - var parameterTypes = parameters.Select(parameter => parameter.ParameterType).ToArray(); - - MethodBuilder methodBuilder = _wrapperBuilder.DefineMethod( - newMethod.Name, - MethodAttributes.Public | MethodAttributes.Virtual, - newMethod.ReturnType, - parameterTypes); - - if (newMethod.IsGenericMethod) - { - methodBuilder.DefineGenericParameters( - newMethod.GetGenericArguments().Select(arg => arg.Name).ToArray()); - } - - ILGenerator ilGenerator = methodBuilder.GetILGenerator(); - - LoadUnderlyingObject(ilGenerator, srcField); - PushParameters(parameters, ilGenerator); - ExecuteMethod(newMethod, parameterTypes, ilGenerator); - Return(ilGenerator); - } - - private static void Return(ILGenerator ilGenerator) - { - ilGenerator.Emit(OpCodes.Ret); - } - - private void ExecuteMethod(MethodBase newMethod, Type[] parameterTypes, ILGenerator ilGenerator) - { - MethodInfo srcMethod = GetMethod(newMethod, parameterTypes); - - if (srcMethod == null) - throw new MissingMethodException("Unable to find method " + newMethod.Name + " on " + _realObjectType.FullName); - - ilGenerator.Emit(OpCodes.Call, srcMethod); - } - - private MethodInfo GetMethod(MethodBase realMethod, Type[] parameterTypes) - { - if (realMethod.IsGenericMethod) - return _realObjectType.GetGenericMethod(realMethod.Name, parameterTypes); - - return _realObjectType.GetMethod(realMethod.Name, parameterTypes); - } - - private static void PushParameters(ICollection parameters, ILGenerator ilGenerator) - { - for (int i = 1; i < parameters.Count + 1; i++) - ilGenerator.Emit(OpCodes.Ldarg, i); - } - - private static void LoadUnderlyingObject(ILGenerator ilGenerator, FieldInfo srcField) - { - ilGenerator.Emit(OpCodes.Ldarg_0); - ilGenerator.Emit(OpCodes.Ldfld, srcField); - } - } - - internal class WrapperDictionary - { - private readonly Dictionary _wrapperTypes = new Dictionary(); - - private static string GenerateKey(Type interfaceType, Type realObjectType) - { - return interfaceType.Name + "_" + realObjectType.Name; - } - - public Type GetType(Type interfaceType, Type realObjectType) - { - string key = GenerateKey(interfaceType, realObjectType); - - if (_wrapperTypes.ContainsKey(key)) - return _wrapperTypes[key]; - - return null; - } - - public void SetType(Type interfaceType, Type realObjectType, Type wrapperType) - { - string key = GenerateKey(interfaceType, realObjectType); - - if (_wrapperTypes.ContainsKey(key)) - _wrapperTypes[key] = wrapperType; - else - _wrapperTypes.Add(key, wrapperType); - } - } -} - -#endif \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs b/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs new file mode 100644 index 00000000..7da01e0c --- /dev/null +++ b/Src/Newtonsoft.Json/Utilities/ReflectionObject.cs @@ -0,0 +1,155 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Resources; +using System.Globalization; +#if NET20 +using Newtonsoft.Json.Utilities.LinqBridge; +#else +using System.Linq; +#endif + +namespace Newtonsoft.Json.Utilities +{ + internal class ReflectionMember + { + public Type MemberType { get; set; } + public Func Getter { get; set; } + public Action Setter { get; set; } + } + + internal class ReflectionObject + { + public ObjectConstructor Creator { get; private set; } + public IDictionary Members { get; private set; } + + public ReflectionObject() + { + Members = new Dictionary(); + } + + public object GetValue(object target, string member) + { + Func getter = Members[member].Getter; + return getter(target); + } + + public void SetValue(object target, string member, object value) + { + Action setter = Members[member].Setter; + setter(target, value); + } + + public Type GetType(string member) + { + return Members[member].MemberType; + } + + public static ReflectionObject Create(Type t, params string[] memberNames) + { + return Create(t, null, memberNames); + } + + public static ReflectionObject Create(Type t, MethodBase creator, params string[] memberNames) + { + ReflectionObject d = new ReflectionObject(); + + ReflectionDelegateFactory delegateFactory = JsonTypeReflector.ReflectionDelegateFactory; + + if (creator != null) + { + d.Creator = delegateFactory.CreateParametrizedConstructor(creator); + } + else + { + if (ReflectionUtils.HasDefaultConstructor(t, false)) + { + Func ctor = delegateFactory.CreateDefaultConstructor(t); + + d.Creator = args => ctor(); + } + } + + foreach (string memberName in memberNames) + { + MemberInfo[] members = t.GetMember(memberName, BindingFlags.Instance | BindingFlags.Public); + if (members.Length != 1) + throw new ArgumentException("Expected a single member with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, memberName)); + + MemberInfo member = members.Single(); + + ReflectionMember reflectionMember = new ReflectionMember(); + + switch (member.MemberType()) + { + case MemberTypes.Field: + case MemberTypes.Property: + if (ReflectionUtils.CanReadMemberValue(member, false)) + reflectionMember.Getter = delegateFactory.CreateGet(member); + + if (ReflectionUtils.CanSetMemberValue(member, false, false)) + reflectionMember.Setter = delegateFactory.CreateSet(member); + break; + case MemberTypes.Method: + MethodInfo method = (MethodInfo)member; + if (method.IsPublic) + { + ParameterInfo[] parameters = method.GetParameters(); + if (parameters.Length == 0 && method.ReturnType != typeof(void)) + { + MethodCall call = delegateFactory.CreateMethodCall(method); + reflectionMember.Getter = target => call(target); + } + else if (parameters.Length == 1 && method.ReturnType == typeof(void)) + { + MethodCall call = delegateFactory.CreateMethodCall(method); + reflectionMember.Setter = (target, arg) => call(target, arg); + } + } + break; + default: + throw new ArgumentException("Unexpected member type '{0}' for member '{1}'.".FormatWith(CultureInfo.InvariantCulture, member.MemberType(), member.Name)); + } + + if (ReflectionUtils.CanReadMemberValue(member, false)) + reflectionMember.Getter = delegateFactory.CreateGet(member); + + if (ReflectionUtils.CanSetMemberValue(member, false, false)) + reflectionMember.Setter = delegateFactory.CreateSet(member); + + reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(member); + + d.Members[memberName] = reflectionMember; + } + + return d; + } + } +} \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index dc824185..c76c84eb 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -429,6 +429,8 @@ namespace Newtonsoft.Json.Utilities return ((PropertyInfo)member).PropertyType; case MemberTypes.Event: return ((EventInfo)member).EventHandlerType; + case MemberTypes.Method: + return ((MethodInfo)member).ReturnType; default: throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member"); } @@ -671,6 +673,11 @@ namespace Newtonsoft.Json.Utilities #if !(NETFX_CORE || PORTABLE) public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute + { + return (T[])GetAttributes(attributeProvider, typeof(T), inherit); + } + + public static Attribute[] GetAttributes(object attributeProvider, Type attributeType, bool inherit) { ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider"); @@ -680,45 +687,50 @@ namespace Newtonsoft.Json.Utilities // ICustomAttributeProvider doesn't do inheritance if (provider is Type) - return (T[])((Type)provider).GetCustomAttributes(typeof(T), inherit); + return (Attribute[])((Type)provider).GetCustomAttributes(attributeType, inherit); if (provider is Assembly) - return (T[])Attribute.GetCustomAttributes((Assembly)provider, typeof(T)); + return Attribute.GetCustomAttributes((Assembly)provider, attributeType); if (provider is MemberInfo) - return (T[])Attribute.GetCustomAttributes((MemberInfo)provider, typeof(T), inherit); + return Attribute.GetCustomAttributes((MemberInfo)provider, attributeType, inherit); #if !PORTABLE40 if (provider is Module) - return (T[])Attribute.GetCustomAttributes((Module)provider, typeof(T), inherit); + return Attribute.GetCustomAttributes((Module)provider, attributeType, inherit); #endif if (provider is ParameterInfo) - return (T[])Attribute.GetCustomAttributes((ParameterInfo)provider, typeof(T), inherit); + return Attribute.GetCustomAttributes((ParameterInfo)provider, attributeType, inherit); #if !PORTABLE40 - return (T[])((ICustomAttributeProvider)attributeProvider).GetCustomAttributes(typeof(T), inherit); + return (Attribute[])((ICustomAttributeProvider)attributeProvider).GetCustomAttributes(attributeType, inherit); #else throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider)); #endif } #else - public static T[] GetAttributes(object provider, bool inherit) where T : Attribute + public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute + { + return GetAttributes(attributeProvider, typeof(T), inherit).Cast().ToArray(); + } + + public static Attribute[] GetAttributes(object provider, Type attributeType, bool inherit) { if (provider is Type) - return ((Type) provider).GetTypeInfo().GetCustomAttributes(inherit).ToArray(); + return ((Type) provider).GetTypeInfo().GetCustomAttributes(attributeType, inherit).ToArray(); if (provider is Assembly) - return ((Assembly) provider).GetCustomAttributes().ToArray(); + return ((Assembly) provider).GetCustomAttributes(attributeType).ToArray(); if (provider is MemberInfo) - return ((MemberInfo) provider).GetCustomAttributes(inherit).ToArray(); + return ((MemberInfo) provider).GetCustomAttributes(attributeType, inherit).ToArray(); if (provider is Module) - return ((Module) provider).GetCustomAttributes().ToArray(); + return ((Module) provider).GetCustomAttributes(attributeType).ToArray(); if (provider is ParameterInfo) - return ((ParameterInfo) provider).GetCustomAttributes(inherit).ToArray(); + return ((ParameterInfo) provider).GetCustomAttributes(attributeType, inherit).ToArray(); throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider)); } @@ -797,6 +809,7 @@ namespace Newtonsoft.Json.Utilities return fieldInfos.Cast(); } +#if !(NETFX_CORE || PORTABLE) private static void GetChildPrivateFields(IList initialFields, Type targetType, BindingFlags bindingAttr) { // fix weirdness with private FieldInfos only being returned for the current Type @@ -816,6 +829,7 @@ namespace Newtonsoft.Json.Utilities } } } +#endif public static IEnumerable GetProperties(Type targetType, BindingFlags bindingAttr) { diff --git a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs index 4cd71194..3618caee 100644 --- a/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs +++ b/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs @@ -571,54 +571,5 @@ namespace Newtonsoft.Json.Utilities Type match; return type.AssignableToTypeName(fullTypeName, out match); } - - public static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes) - { - var methods = type.GetMethods().Where(method => method.Name == name); - - foreach (var method in methods) - { - if (method.HasParameters(parameterTypes)) - return method; - } - - return null; - } - - public static bool HasParameters(this MethodInfo method, params Type[] parameterTypes) - { - var methodParameters = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray(); - - if (methodParameters.Length != parameterTypes.Length) - return false; - - for (int i = 0; i < methodParameters.Length; i++) - if (methodParameters[i].ToString() != parameterTypes[i].ToString()) - return false; - - return true; - } - - public static IEnumerable GetAllInterfaces(this Type target) - { - foreach (var i in target.GetInterfaces()) - { - yield return i; - foreach (var ci in i.GetInterfaces()) - { - yield return ci; - } - } - } - - public static IEnumerable GetAllMethods(this Type target) - { - var allTypes = target.GetAllInterfaces().ToList(); - allTypes.Add(target); - - return from type in allTypes - from method in type.GetMethods() - select method; - } } } \ No newline at end of file