-Refactored dynamic type wrapping

-Improved KeyValuePairConverter performance
This commit is contained in:
James Newton-King
2014-06-20 19:03:36 +12:00
parent 6b08fbc2fa
commit 9203e97312
20 changed files with 316 additions and 478 deletions
@@ -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")]
@@ -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<JsonReaderException>(
"Input string '020474068' is not a valid number. Path '', line 1, position 9.",
() => JsonConvert.DeserializeObject<string>("020474068"));
}
[Test]
public void DeserializedDerivedWithPrivate()
{
string json = @"{
""DerivedProperty"": ""derived"",
""BaseProperty"": ""base""
}";
var d = JsonConvert.DeserializeObject<DerivedWithPrivate>(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<T>
@@ -32,13 +32,6 @@ using System.Collections.Generic;
namespace Newtonsoft.Json.Converters
{
#if !NET20
internal interface IBinary
{
byte[] ToArray();
}
#endif
/// <summary>
/// Converts a binary value to and from a base 64 string value.
/// </summary>
@@ -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
/// <summary>
@@ -72,8 +67,8 @@ namespace Newtonsoft.Json.Converters
#if !(NET20)
if (value.GetType().AssignableToTypeName(BinaryTypeName))
{
IBinary binary = DynamicWrapper.CreateWrapper<IBinary>(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
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
@@ -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
@@ -31,12 +31,6 @@ using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Converters
{
internal interface IEntityKeyMember
{
string Key { get; set; }
object Value { get; set; }
}
/// <summary>
/// Converts an Entity Framework EntityKey to and from JSON.
/// </summary>
@@ -48,6 +42,8 @@ namespace Newtonsoft.Json.Converters
private const string TypePropertyName = "Type";
private const string ValuePropertyName = "Value";
private static ReflectionObject _reflectionObject;
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
@@ -56,26 +52,30 @@ namespace Newtonsoft.Json.Converters
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
EnsureReflectionObject(value.GetType());
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(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
/// <returns>The object value.</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(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);
}
/// <summary>
@@ -39,6 +39,17 @@ namespace Newtonsoft.Json.Converters
private const string KeyName = "Key";
private const string ValueName = "Value";
private static readonly ThreadSafeStore<Type, ReflectionObject> ReflectionObjectPerType = new ThreadSafeStore<Type, ReflectionObject>(InitializeReflectionObject);
private static ReflectionObject InitializeReflectionObject(Type t)
{
IList<Type> genericArguments = t.GetGenericArguments();
Type keyType = genericArguments[0];
Type valueType = genericArguments[1];
return ReflectionObject.Create(t, t.GetConstructor(new[] { keyType, valueType }), KeyName, ValueName);
}
/// <summary>
/// Writes the JSON representation of the object.
/// </summary>
@@ -47,22 +58,15 @@ namespace Newtonsoft.Json.Converters
/// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type t = value.GetType();
IList<Type> 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<Type> 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);
}
/// <summary>
+2
View File
@@ -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 };
@@ -224,17 +224,16 @@
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\CachedAttributeGetter.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Serialization\ReflectionValueProvider.cs" />
<Compile Include="Utilities\Base64Encoder.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\ILGeneratorExtensions.cs" />
<Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
<Compile Include="Utilities\MethodCall.cs" />
<Compile Include="Utilities\ReflectionDelegateFactory.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\StringReference.cs" />
<Compile Include="Utilities\ThreadSafeStore.cs" />
<Compile Include="TypeNameHandling.cs" />
@@ -231,13 +231,11 @@
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\CachedAttributeGetter.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\ReflectionValueProvider.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Utilities\Base64Encoder.cs" />
<Compile Include="Utilities\DynamicProxyMetaObject.cs" />
<Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
@@ -248,6 +246,7 @@
<Compile Include="Utilities\ReflectionDelegateFactory.cs" />
<Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
<Compile Include="Utilities\MethodCall.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\StringReference.cs" />
<Compile Include="Utilities\ThreadSafeStore.cs" />
<Compile Include="TypeNameHandling.cs" />
@@ -231,13 +231,11 @@
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\CachedAttributeGetter.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\ReflectionValueProvider.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
<Compile Include="Utilities\Base64Encoder.cs" />
<Compile Include="Utilities\DynamicProxyMetaObject.cs" />
<Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
@@ -248,6 +246,7 @@
<Compile Include="Utilities\ReflectionDelegateFactory.cs" />
<Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
<Compile Include="Utilities\MethodCall.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\StringReference.cs" />
<Compile Include="Utilities\ThreadSafeStore.cs" />
<Compile Include="TypeNameHandling.cs" />
@@ -186,7 +186,6 @@
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\MemoryTraceWriter.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
@@ -209,7 +208,6 @@
<Compile Include="Utilities\DynamicProxyMetaObject.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\EnumUtils.cs" />
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.cs" />
@@ -223,6 +221,7 @@
<Compile Include="Utilities\MethodCall.cs" />
<Compile Include="Utilities\MiscellaneousUtils.cs" />
<Compile Include="Utilities\ReflectionDelegateFactory.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\ReflectionUtils.cs" />
<Compile Include="Utilities\StringBuffer.cs" />
<Compile Include="Utilities\StringReference.cs" />
@@ -191,7 +191,6 @@
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\MemoryTraceWriter.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
@@ -213,7 +212,6 @@
<Compile Include="Utilities\DynamicProxyMetaObject.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\EnumUtils.cs" />
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.cs" />
@@ -227,6 +225,7 @@
<Compile Include="Utilities\MethodCall.cs" />
<Compile Include="Utilities\MiscellaneousUtils.cs" />
<Compile Include="Utilities\ReflectionDelegateFactory.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\ReflectionUtils.cs" />
<Compile Include="Utilities\StringBuffer.cs" />
<Compile Include="Utilities\StringReference.cs" />
+1 -2
View File
@@ -190,7 +190,6 @@
<Compile Include="Serialization\JsonSerializerProxy.cs" />
<Compile Include="Serialization\JsonStringContract.cs" />
<Compile Include="Serialization\JsonTypeReflector.cs" />
<Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
<Compile Include="Serialization\MemoryTraceWriter.cs" />
<Compile Include="Serialization\ObjectConstructor.cs" />
<Compile Include="Serialization\OnErrorAttribute.cs" />
@@ -212,7 +211,7 @@
<Compile Include="Utilities\DynamicProxyMetaObject.cs" />
<Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
<Compile Include="Utilities\DynamicUtils.cs" />
<Compile Include="Utilities\DynamicWrapper.cs" />
<Compile Include="Utilities\ReflectionObject.cs" />
<Compile Include="Utilities\EnumUtils.cs" />
<Compile Include="Utilities\EnumValue.cs" />
<Compile Include="Utilities\EnumValues.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)]
@@ -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<object, Type> JsonConverterTypeCache = new ThreadSafeStore<object, Type>(GetJsonConverterTypeFromAttribute);
#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
#if !(NET20 || NETFX_CORE)
private static readonly ThreadSafeStore<Type, Type> AssociatedMetadataTypesCache = new ThreadSafeStore<Type, Type>(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<IMetadataTypeAttribute>(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
@@ -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
@@ -160,6 +160,7 @@ namespace Newtonsoft.Json.Utilities
#endif
};
#if !(NETFX_CORE || PORTABLE)
private static readonly List<TypeInformation> PrimitiveTypeCodes = new List<TypeInformation>
{
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)
{
@@ -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<T>(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<ParameterInfo> 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<string, Type> _wrapperTypes = new Dictionary<string, Type>();
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
@@ -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<object, object> Getter { get; set; }
public Action<object, object> Setter { get; set; }
}
internal class ReflectionObject
{
public ObjectConstructor<object> Creator { get; private set; }
public IDictionary<string, ReflectionMember> Members { get; private set; }
public ReflectionObject()
{
Members = new Dictionary<string, ReflectionMember>();
}
public object GetValue(object target, string member)
{
Func<object, object> getter = Members[member].Getter;
return getter(target);
}
public void SetValue(object target, string member, object value)
{
Action<object, object> 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<object> ctor = delegateFactory.CreateDefaultConstructor<object>(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<object>(member);
if (ReflectionUtils.CanSetMemberValue(member, false, false))
reflectionMember.Setter = delegateFactory.CreateSet<object>(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<object, object> call = delegateFactory.CreateMethodCall<object>(method);
reflectionMember.Getter = target => call(target);
}
else if (parameters.Length == 1 && method.ReturnType == typeof(void))
{
MethodCall<object, object> call = delegateFactory.CreateMethodCall<object>(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<object>(member);
if (ReflectionUtils.CanSetMemberValue(member, false, false))
reflectionMember.Setter = delegateFactory.CreateSet<object>(member);
reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(member);
d.Members[memberName] = reflectionMember;
}
return d;
}
}
}
@@ -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<T>(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<T>(object provider, bool inherit) where T : Attribute
public static T[] GetAttributes<T>(object attributeProvider, bool inherit) where T : Attribute
{
return GetAttributes(attributeProvider, typeof(T), inherit).Cast<T>().ToArray();
}
public static Attribute[] GetAttributes(object provider, Type attributeType, bool inherit)
{
if (provider is Type)
return ((Type) provider).GetTypeInfo().GetCustomAttributes<T>(inherit).ToArray();
return ((Type) provider).GetTypeInfo().GetCustomAttributes(attributeType, inherit).ToArray();
if (provider is Assembly)
return ((Assembly) provider).GetCustomAttributes<T>().ToArray();
return ((Assembly) provider).GetCustomAttributes(attributeType).ToArray();
if (provider is MemberInfo)
return ((MemberInfo) provider).GetCustomAttributes<T>(inherit).ToArray();
return ((MemberInfo) provider).GetCustomAttributes(attributeType, inherit).ToArray();
if (provider is Module)
return ((Module) provider).GetCustomAttributes<T>().ToArray();
return ((Module) provider).GetCustomAttributes(attributeType).ToArray();
if (provider is ParameterInfo)
return ((ParameterInfo) provider).GetCustomAttributes<T>(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<FieldInfo>();
}
#if !(NETFX_CORE || PORTABLE)
private static void GetChildPrivateFields(IList<MemberInfo> 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<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
{
@@ -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<Type> 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<MethodInfo> GetAllMethods(this Type target)
{
var allTypes = target.GetAllInterfaces().ToList();
allTypes.Add(target);
return from type in allTypes
from method in type.GetMethods()
select method;
}
}
}