-Refactored dynamic type wrapping
-Improved KeyValuePairConverter performance
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user