Merge branch 'master' of github.com:JamesNK/Newtonsoft.Json

This commit is contained in:
James Newton-King
2013-03-11 19:23:59 +13:00
8 changed files with 187 additions and 103 deletions
@@ -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;
+58 -93
View File
@@ -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