Merge branch 'master' of github.com:JamesNK/Newtonsoft.Json
This commit is contained in:
@@ -63,10 +63,13 @@ namespace Newtonsoft.Json.Tests.Serialization
|
||||
|
||||
Dictionary<string, object> values = new Dictionary<string, object>();
|
||||
|
||||
IContractResolver c = DefaultContractResolver.Instance;
|
||||
JsonDynamicContract dynamicContract = (JsonDynamicContract)c.ResolveContract(dynamicObject.GetType());
|
||||
|
||||
foreach (string memberName in dynamicObject.GetDynamicMemberNames())
|
||||
{
|
||||
object value;
|
||||
dynamicObject.TryGetMember(memberName, out value);
|
||||
dynamicContract.TryGetMember(dynamicObject, memberName, out value);
|
||||
|
||||
values.Add(memberName, value);
|
||||
}
|
||||
|
||||
@@ -6638,6 +6638,43 @@ Parameter name: value",
|
||||
}", json);
|
||||
}
|
||||
|
||||
public class EnumerableClass<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly IList<T> _values;
|
||||
|
||||
public EnumerableClass(IEnumerable<T> values)
|
||||
{
|
||||
_values = new List<T>(values);
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return _values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeserializeIEnumerableFromConstructor()
|
||||
{
|
||||
string json = @"[
|
||||
""One"",
|
||||
""II"",
|
||||
""3""
|
||||
]";
|
||||
|
||||
var result = JsonConvert.DeserializeObject<EnumerableClass<string>>(json);
|
||||
|
||||
Assert.AreEqual(3, result.Count());
|
||||
Assert.AreEqual("One", result.ElementAt(0));
|
||||
Assert.AreEqual("II", result.ElementAt(1));
|
||||
Assert.AreEqual("3", result.ElementAt(2));
|
||||
}
|
||||
|
||||
[JsonObject(MemberSerialization.Fields)]
|
||||
public class MyTuple<T1>
|
||||
{
|
||||
|
||||
@@ -974,16 +974,14 @@ namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
manager.PushScope();
|
||||
|
||||
string namespacePrefix = null;
|
||||
string namespaceUri = null;
|
||||
foreach (IXmlNode attribute in node.Attributes)
|
||||
{
|
||||
if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/")
|
||||
{
|
||||
namespacePrefix = (attribute.LocalName != "xmlns")
|
||||
string namespacePrefix = (attribute.LocalName != "xmlns")
|
||||
? attribute.LocalName
|
||||
: string.Empty;
|
||||
namespaceUri = attribute.Value;
|
||||
string namespaceUri = attribute.Value;
|
||||
|
||||
manager.AddNamespace(namespacePrefix, namespaceUri);
|
||||
}
|
||||
@@ -1017,9 +1015,6 @@ namespace Newtonsoft.Json.Converters
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
if (namespacePrefix != null)
|
||||
manager.RemoveNamespace(namespacePrefix, namespaceUri);
|
||||
|
||||
manager.PopScope();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
#if !(NET35 || NET20 || WINDOWS_PHONE)
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Newtonsoft.Json.Utilities;
|
||||
using System.Collections;
|
||||
|
||||
@@ -49,6 +51,26 @@ namespace Newtonsoft.Json.Serialization
|
||||
/// <value>The property name resolver.</value>
|
||||
public Func<string, string> PropertyNameResolver { get; set; }
|
||||
|
||||
private readonly ThreadSafeStore<string, CallSite<Func<CallSite, object, object>>> _callSiteGetters =
|
||||
new ThreadSafeStore<string, CallSite<Func<CallSite, object, object>>>(CreateCallSiteGetter);
|
||||
|
||||
private readonly ThreadSafeStore<string, CallSite<Func<CallSite, object, object, object>>> _callSiteSetters =
|
||||
new ThreadSafeStore<string, CallSite<Func<CallSite, object, object, object>>>(CreateCallSiteSetter);
|
||||
|
||||
private static CallSite<Func<CallSite, object, object>> CreateCallSiteGetter(string name)
|
||||
{
|
||||
GetMemberBinder getMemberBinder = (GetMemberBinder)DynamicUtils.BinderWrapper.GetMember(name, typeof(DynamicUtils));
|
||||
|
||||
return CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(getMemberBinder));
|
||||
}
|
||||
|
||||
private static CallSite<Func<CallSite, object, object, object>> CreateCallSiteSetter(string name)
|
||||
{
|
||||
SetMemberBinder binder = (SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils));
|
||||
|
||||
return CallSite<Func<CallSite, object, object, object>>.Create(new NoThrowSetBinderMember(binder));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonDynamicContract"/> class.
|
||||
/// </summary>
|
||||
@@ -60,6 +82,37 @@ namespace Newtonsoft.Json.Serialization
|
||||
|
||||
Properties = new JsonPropertyCollection(UnderlyingType);
|
||||
}
|
||||
|
||||
internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
|
||||
|
||||
CallSite<Func<CallSite, object, object>> callSite = _callSiteGetters.Get(name);
|
||||
|
||||
object result = callSite.Target(callSite, dynamicProvider);
|
||||
|
||||
if (!ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult))
|
||||
{
|
||||
value = result;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
|
||||
|
||||
CallSite<Func<CallSite, object, object, object>> callSite = _callSiteSetters.Get(name);
|
||||
|
||||
object result = callSite.Target(callSite, dynamicProvider, value);
|
||||
|
||||
return !ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -593,6 +593,10 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
{
|
||||
list = (IList) ReflectionUtils.CreateInstance(contract.CreatedType, list);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReflectionUtils.CreateInstance(contract.CreatedType, list);
|
||||
}
|
||||
}
|
||||
else if (list is IWrappedCollection)
|
||||
{
|
||||
@@ -610,6 +614,7 @@ To fix this error either change the JSON to a {1} or change the deserialized typ
|
||||
{
|
||||
value = CreateJToken(reader, contract);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1274,7 +1279,7 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
else
|
||||
value = CreateValueInternal(reader, t, dynamicMemberContract, null, null, member, null);
|
||||
|
||||
newObject.TrySetMember(memberName, value);
|
||||
contract.TrySetMember(newObject, memberName, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -750,7 +750,7 @@ To fix this error either change the environment to be fully trusted, change the
|
||||
foreach (string memberName in value.GetDynamicMemberNames())
|
||||
{
|
||||
object memberValue;
|
||||
if (value.TryGetMember(memberName, out memberValue))
|
||||
if (contract.TryGetMember(value, memberName, out memberValue))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -226,6 +226,32 @@ namespace Newtonsoft.Json.Utilities
|
||||
else
|
||||
list = null;
|
||||
}
|
||||
else if (ReflectionUtils.ImplementsGenericDefinition(listType, typeof (IEnumerable<>), out collectionType))
|
||||
{
|
||||
bool suitableConstructor = false;
|
||||
|
||||
foreach (ConstructorInfo constructor in listType.GetConstructors())
|
||||
{
|
||||
IList<ParameterInfo> parameters = constructor.GetParameters();
|
||||
|
||||
if (parameters.Count == 1)
|
||||
{
|
||||
if (collectionType.IsAssignableFrom(parameters[0].ParameterType))
|
||||
{
|
||||
suitableConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!suitableConstructor)
|
||||
throw new Exception("{0} does not have a public constructor that takes a type that implements {1}.".FormatWith(CultureInfo.InvariantCulture, listType, collectionType));
|
||||
|
||||
Type collectionContentsType = collectionType.GetGenericArguments()[0];
|
||||
|
||||
list = CreateGenericList(collectionContentsType);
|
||||
isReadOnlyOrFixedSize = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
list = null;
|
||||
|
||||
@@ -85,8 +85,8 @@ namespace Newtonsoft.Json.Utilities
|
||||
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) });
|
||||
object arg = createArgumentInfoMethod.Invoke(null, new object[] { 0, null });
|
||||
MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] {csharpArgumentInfoFlags, typeof (string)});
|
||||
object arg = createArgumentInfoMethod.Invoke(null, new object[] {0, null});
|
||||
a.SetValue(arg, i);
|
||||
}
|
||||
|
||||
@@ -99,127 +99,92 @@ namespace Newtonsoft.Json.Utilities
|
||||
Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName);
|
||||
Type binderType = Type.GetType(BinderTypeName);
|
||||
|
||||
Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType);
|
||||
Type csharpArgumentInfoTypeEnumerableType = typeof (IEnumerable<>).MakeGenericType(csharpArgumentInfoType);
|
||||
|
||||
MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
|
||||
MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] {csharpBinderFlagsType, typeof (string), typeof (Type), csharpArgumentInfoTypeEnumerableType});
|
||||
_getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getMemberMethod);
|
||||
|
||||
MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
|
||||
MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] {csharpBinderFlagsType, typeof (string), typeof (Type), csharpArgumentInfoTypeEnumerableType});
|
||||
_setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(setMemberMethod);
|
||||
}
|
||||
|
||||
public static CallSiteBinder GetMember(string name, Type context)
|
||||
{
|
||||
Init();
|
||||
return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
|
||||
return (CallSiteBinder) _getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
|
||||
}
|
||||
|
||||
public static CallSiteBinder SetMember(string name, Type context)
|
||||
{
|
||||
Init();
|
||||
return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
|
||||
return (CallSiteBinder) _setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetMember(this IDynamicMetaObjectProvider dynamicProvider, string name, out object value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
|
||||
|
||||
GetMemberBinder getMemberBinder = (GetMemberBinder) BinderWrapper.GetMember(name, typeof (DynamicUtils));
|
||||
|
||||
CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(getMemberBinder));
|
||||
|
||||
object result = callSite.Target(callSite, dynamicProvider);
|
||||
|
||||
if (!ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult))
|
||||
{
|
||||
value = result;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TrySetMember(this IDynamicMetaObjectProvider dynamicProvider, string name, object value)
|
||||
{
|
||||
ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
|
||||
|
||||
SetMemberBinder binder = (SetMemberBinder)BinderWrapper.SetMember(name, typeof(DynamicUtils));
|
||||
|
||||
var setterSite = CallSite<Func<CallSite, object, object, object>>.Create(new NoThrowSetBinderMember(binder));
|
||||
|
||||
object result = setterSite.Target(setterSite, dynamicProvider, value);
|
||||
|
||||
return !ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider)
|
||||
{
|
||||
DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider));
|
||||
return metaObject.GetDynamicMemberNames();
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowGetBinderMember : GetMemberBinder
|
||||
internal class NoThrowGetBinderMember : GetMemberBinder
|
||||
{
|
||||
private readonly GetMemberBinder _innerBinder;
|
||||
|
||||
public NoThrowGetBinderMember(GetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
private readonly GetMemberBinder _innerBinder;
|
||||
|
||||
public NoThrowGetBinderMember(GetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
|
||||
internal class NoThrowSetBinderMember : SetMemberBinder
|
||||
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
private readonly SetMemberBinder _innerBinder;
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
|
||||
|
||||
public NoThrowSetBinderMember(SetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value });
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class NoThrowExpressionVisitor : ExpressionVisitor
|
||||
{
|
||||
internal static readonly object ErrorResult = new object();
|
||||
|
||||
protected override Expression VisitConditional(ConditionalExpression node)
|
||||
{
|
||||
// if the result of a test is to throw an error, rewrite to result an error result value
|
||||
if (node.IfFalse.NodeType == ExpressionType.Throw)
|
||||
return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult));
|
||||
|
||||
return base.VisitConditional(node);
|
||||
}
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowSetBinderMember : SetMemberBinder
|
||||
{
|
||||
private readonly SetMemberBinder _innerBinder;
|
||||
|
||||
public NoThrowSetBinderMember(SetMemberBinder innerBinder)
|
||||
: base(innerBinder.Name, innerBinder.IgnoreCase)
|
||||
{
|
||||
_innerBinder = innerBinder;
|
||||
}
|
||||
|
||||
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
|
||||
{
|
||||
DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value });
|
||||
|
||||
NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
|
||||
Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
|
||||
|
||||
DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
|
||||
return finalMetaObject;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoThrowExpressionVisitor : ExpressionVisitor
|
||||
{
|
||||
internal static readonly object ErrorResult = new object();
|
||||
|
||||
protected override Expression VisitConditional(ConditionalExpression node)
|
||||
{
|
||||
// if the result of a test is to throw an error, rewrite to result an error result value
|
||||
if (node.IfFalse.NodeType == ExpressionType.Throw)
|
||||
return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult));
|
||||
|
||||
return base.VisitConditional(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user